Is.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include <boost/lexical_cast.hpp>
  2. #include "Is.h"
  3. #include "Renderer.h"
  4. #include "Camera.h"
  5. #include "Light.h"
  6. #include "PointLight.h"
  7. #include "SpotLight.h"
  8. #include "LightData.h"
  9. #include "App.h"
  10. #include "Scene.h"
  11. #include "LightData.h"
  12. #include "Collision.h"
  13. #include "Vao.h"
  14. #include "Sm.h"
  15. #include "Smo.h"
  16. //======================================================================================================================
  17. // Constructor =
  18. //======================================================================================================================
  19. Is::Is(Renderer& r_, Object* parent):
  20. RenderingPass(r_, parent),
  21. sm(new Sm(r_, this)),
  22. smo(new Smo(r_, this))
  23. {}
  24. //======================================================================================================================
  25. // calcViewVectors =
  26. //======================================================================================================================
  27. void Is::calcViewVectors()
  28. {
  29. Vec3 viewVectors[4];
  30. const Camera& cam = r.getCamera();
  31. const uint& w = r.getWidth();
  32. const uint& h = r.getHeight();
  33. // From right up and CC wise to right down, Just like we render the quad
  34. uint pixels[4][2]={{w, h}, {0, h}, {0, 0}, {w, 0}};
  35. uint viewport[4]={0, 0, w, h};
  36. for(int i=0; i<4; i++)
  37. {
  38. /*
  39. Original Code:
  40. Renderer::unProject(pixels[i][0], pixels[i][1], 10, cam.getViewMatrix(), cam.getProjectionMatrix(), viewport,
  41. viewVectors[i].x, viewVectors[i].y, viewVectors[i].z);
  42. viewVectors[i] = cam.getViewMatrix() * viewVectors[i];
  43. The original code is the above 3 lines. The optimized follows:
  44. */
  45. Vec3 vec;
  46. vec.x = (2.0 * (pixels[i][0] - viewport[0])) / viewport[2] - 1.0;
  47. vec.y = (2.0 * (pixels[i][1] - viewport[1])) / viewport[3] - 1.0;
  48. vec.z = 1.0;
  49. viewVectors[i] = vec.getTransformed(cam.getInvProjectionMatrix());
  50. // end of optimized code
  51. }
  52. RASSERT_THROW_EXCEPTION(sizeof(viewVectors) != viewVectorsVbo->getSizeInBytes());
  53. viewVectorsVbo->write(viewVectors);
  54. }
  55. //======================================================================================================================
  56. // calcPlanes =
  57. //======================================================================================================================
  58. void Is::calcPlanes()
  59. {
  60. const Camera& cam = r.getCamera();
  61. planes.x = cam.getZFar() / (cam.getZNear() - cam.getZFar());
  62. planes.y = (cam.getZFar() * cam.getZNear()) / (cam.getZNear() -cam.getZFar());
  63. }
  64. //======================================================================================================================
  65. // initFbo =
  66. //======================================================================================================================
  67. void Is::initFbo()
  68. {
  69. try
  70. {
  71. // create FBO
  72. fbo.create();
  73. fbo.bind();
  74. // init the stencil render buffer
  75. glGenRenderbuffers(1, &stencilRb);
  76. glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
  77. glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, r.getWidth(), r.getHeight());
  78. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRb);
  79. // inform in what buffers we draw
  80. fbo.setNumOfColorAttachements(1);
  81. // create the FAI
  82. fai.createEmpty2D(r.getWidth(), r.getHeight(), GL_RGB, GL_RGB, GL_FLOAT);
  83. // attach
  84. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fai.getGlId(), 0);
  85. //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, r.ms.depthFai.getGlId(), 0);
  86. // test if success
  87. fbo.checkIfGood();
  88. // unbind
  89. fbo.unbind();
  90. }
  91. catch(std::exception& e)
  92. {
  93. throw EXCEPTION("Cannot create deferred shading illumination stage FBO: " + e.what());
  94. }
  95. }
  96. //======================================================================================================================
  97. // init =
  98. //======================================================================================================================
  99. void Is::init(const RendererInitializer& initializer)
  100. {
  101. // init passes
  102. smo->init(initializer);
  103. sm->init(initializer);
  104. // load the shaders
  105. ambientPassSProg.loadRsrc("shaders/IsAp.glsl");
  106. // point light
  107. pointLightSProg.loadRsrc(ShaderProg::createSrcCodeToCache("shaders/IsLpGeneric.glsl", "#define POINT_LIGHT_ENABLED\n",
  108. "Point").c_str());
  109. // spot light no shadow
  110. spotLightNoShadowSProg.loadRsrc(ShaderProg::createSrcCodeToCache("shaders/IsLpGeneric.glsl",
  111. "#define SPOT_LIGHT_ENABLED\n",
  112. "SpotNoShadow").c_str());
  113. // spot light w/t shadow
  114. std::string pps = std::string("\n#define SPOT_LIGHT_ENABLED\n#define SHADOW_ENABLED\n") +
  115. "#define SHADOWMAP_SIZE " + boost::lexical_cast<std::string>(sm->getResolution()) + "\n";
  116. std::string prefix = "SpotShadowSmSize" + boost::lexical_cast<std::string>(sm->getResolution());
  117. if(sm->isPcfEnabled())
  118. {
  119. pps += "#define PCF_ENABLED\n";
  120. prefix += "Pcf";
  121. }
  122. spotLightShadowSProg.loadRsrc(ShaderProg::createSrcCodeToCache("shaders/IsLpGeneric.glsl", pps.c_str(),
  123. prefix.c_str()).c_str());
  124. // init the rest
  125. initFbo();
  126. // The VBOs and VAOs
  127. float quadVertCoords[][2] = {{1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0}};
  128. quadPositionsVbo = new Vbo(GL_ARRAY_BUFFER, sizeof(quadVertCoords), quadVertCoords, GL_STATIC_DRAW, this);
  129. ushort quadVertIndeces[2][3] = {{0, 1, 3}, {1, 2, 3}};
  130. quadVertIndecesVbo = new Vbo(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadVertIndeces), quadVertIndeces, GL_STATIC_DRAW, this);
  131. viewVectorsVbo = new Vbo(GL_ARRAY_BUFFER, 4 * sizeof(Vec3), NULL, GL_DYNAMIC_DRAW, this);
  132. vao = new Vao(this);
  133. vao->attachArrayBufferVbo(*quadPositionsVbo, 0, 2, GL_FLOAT, false, 0, NULL);
  134. vao->attachArrayBufferVbo(*viewVectorsVbo, 1, 3, GL_FLOAT, false, 0, NULL);
  135. vao->attachElementArrayBufferVbo(*quadVertIndecesVbo);
  136. }
  137. //======================================================================================================================
  138. // drawLightPassQuad =
  139. //======================================================================================================================
  140. void Is::drawLightPassQuad() const
  141. {
  142. vao->bind();
  143. glDrawElements(GL_TRIANGLES, 2 * 3, GL_UNSIGNED_SHORT, 0);
  144. vao->unbind();
  145. ON_GL_FAIL_THROW_EXCEPTION();
  146. }
  147. //======================================================================================================================
  148. // ambientPass =
  149. //======================================================================================================================
  150. void Is::ambientPass(const Vec3& color)
  151. {
  152. glDisable(GL_BLEND);
  153. // set the shader
  154. ambientPassSProg->bind();
  155. // set the uniforms
  156. ambientPassSProg->findUniVar("ambientCol")->setVec3(&color);
  157. ambientPassSProg->findUniVar("sceneColMap")->setTexture(r.getMs().getDiffuseFai(), 0);
  158. // Draw quad
  159. r.drawQuad();
  160. }
  161. //======================================================================================================================
  162. // pointLightPass =
  163. //======================================================================================================================
  164. void Is::pointLightPass(const PointLight& light)
  165. {
  166. const Camera& cam = r.getCamera();
  167. // frustum test
  168. Sphere sphere(light.getWorldTransform().origin, light.getRadius());
  169. if(!cam.insideFrustum(sphere))
  170. {
  171. return;
  172. }
  173. // stencil optimization
  174. smo->run(light);
  175. // shader prog
  176. const ShaderProg& shader = *pointLightSProg; // ensure the const-ness
  177. shader.bind();
  178. shader.findUniVar("msNormalFai")->setTexture(r.getMs().getNormalFai(), 0);
  179. shader.findUniVar("msDiffuseFai")->setTexture(r.getMs().getDiffuseFai(), 1);
  180. shader.findUniVar("msSpecularFai")->setTexture(r.getMs().getSpecularFai(), 2);
  181. shader.findUniVar("msDepthFai")->setTexture(r.getMs().getDepthFai(), 3);
  182. shader.findUniVar("planes")->setVec2(&planes);
  183. Vec3 lightPosEyeSpace = light.getWorldTransform().origin.getTransformed(cam.getViewMatrix());
  184. shader.findUniVar("lightPos")->setVec3(&lightPosEyeSpace);
  185. shader.findUniVar("lightRadius")->setFloat(light.getRadius());
  186. shader.findUniVar("lightDiffuseCol")->setVec3(&light.lightData->getDiffuseCol());
  187. shader.findUniVar("lightSpecularCol")->setVec3(&light.lightData->getSpecularCol());
  188. // render quad
  189. drawLightPassQuad();
  190. }
  191. //======================================================================================================================
  192. // spotLightPass =
  193. //======================================================================================================================
  194. void Is::spotLightPass(const SpotLight& light)
  195. {
  196. const Camera& cam = r.getCamera();
  197. // frustum test
  198. if(!cam.insideFrustum(light.getCamera()))
  199. {
  200. return;
  201. }
  202. // shadow mapping
  203. if(light.castsShadow() && sm->isEnabled())
  204. {
  205. sm->run(light.getCamera());
  206. // restore the IS FBO
  207. fbo.bind();
  208. // and restore blending and depth test
  209. glEnable(GL_BLEND);
  210. glBlendFunc(GL_ONE, GL_ONE);
  211. glDisable(GL_DEPTH_TEST);
  212. Renderer::setViewport(0, 0, r.getWidth(), r.getHeight());
  213. }
  214. // stencil optimization
  215. smo->run(light);
  216. // set the texture
  217. light.lightData->getTexture().setRepeat(false);
  218. // shader prog
  219. const ShaderProg* shdr;
  220. if(light.castsShadow() && sm->isEnabled())
  221. {
  222. shdr = spotLightShadowSProg.get();
  223. }
  224. else
  225. {
  226. shdr = spotLightNoShadowSProg.get();
  227. }
  228. shdr->bind();
  229. // bind the FAIs
  230. shdr->findUniVar("msNormalFai")->setTexture(r.getMs().getNormalFai(), 0);
  231. shdr->findUniVar("msDiffuseFai")->setTexture(r.getMs().getDiffuseFai(), 1);
  232. shdr->findUniVar("msSpecularFai")->setTexture(r.getMs().getSpecularFai(), 2);
  233. shdr->findUniVar("msDepthFai")->setTexture(r.getMs().getDepthFai(), 3);
  234. // the planes
  235. shdr->findUniVar("planes")->setVec2(&planes);
  236. // the light params
  237. Vec3 lightPosEyeSpace = light.getWorldTransform().origin.getTransformed(cam.getViewMatrix());
  238. shdr->findUniVar("lightPos")->setVec3(&lightPosEyeSpace);
  239. shdr->findUniVar("lightRadius")->setFloat(light.getDistance());
  240. shdr->findUniVar("lightDiffuseCol")->setVec3(&light.lightData->getDiffuseCol());
  241. shdr->findUniVar("lightSpecularCol")->setVec3(&light.lightData->getSpecularCol());
  242. shdr->findUniVar("lightTex")->setTexture(light.lightData->getTexture(), 4);
  243. // set texture matrix for texture & shadowmap projection
  244. // Bias * P_light * V_light * inv(V_cam)
  245. static Mat4 biasMat4(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
  246. Mat4 texProjectionMat;
  247. texProjectionMat = biasMat4 * light.getCamera().getProjectionMatrix() *
  248. Mat4::combineTransformations(light.getCamera().getViewMatrix(), Mat4(cam.getWorldTransform()));
  249. shdr->findUniVar("texProjectionMat")->setMat4(&texProjectionMat);
  250. // the shadowmap
  251. if(light.castsShadow() && sm->isEnabled())
  252. {
  253. shdr->findUniVar("shadowMap")->setTexture(sm->shadowMap, 5);
  254. }
  255. // render quad
  256. drawLightPassQuad();
  257. }
  258. //======================================================================================================================
  259. // run =
  260. //======================================================================================================================
  261. void Is::run()
  262. {
  263. // FBO
  264. fbo.bind();
  265. // OGL stuff
  266. Renderer::setViewport(0, 0, r.getWidth(), r.getHeight());
  267. glDisable(GL_DEPTH_TEST);
  268. // ambient pass
  269. ambientPass(app->getScene().getAmbientCol());
  270. // light passes
  271. glEnable(GL_BLEND);
  272. glBlendFunc(GL_ONE, GL_ONE);
  273. glEnable(GL_STENCIL_TEST);
  274. calcViewVectors();
  275. calcPlanes();
  276. // for all lights
  277. for(uint i=0; i<app->getScene().lights.size(); i++)
  278. {
  279. const Light& light = *app->getScene().lights[i];
  280. switch(light.getType())
  281. {
  282. case Light::LT_POINT:
  283. {
  284. const PointLight& pointl = static_cast<const PointLight&>(light);
  285. pointLightPass(pointl);
  286. break;
  287. }
  288. case Light::LT_SPOT:
  289. {
  290. const SpotLight& projl = static_cast<const SpotLight&>(light);
  291. spotLightPass(projl);
  292. break;
  293. }
  294. default:
  295. RASSERT_THROW_EXCEPTION("WTF?");
  296. }
  297. }
  298. glDisable(GL_STENCIL_TEST);
  299. // FBO
  300. fbo.unbind();
  301. ON_GL_FAIL_THROW_EXCEPTION();
  302. }