Is.cpp 14 KB

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