Is.cpp 15 KB

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