Sm.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <boost/foreach.hpp>
  2. #include "Sm.h"
  3. #include "Renderer.h"
  4. #include "Core/App.h"
  5. #include "Scene/Scene.h"
  6. #include "Resources/LightRsrc.h"
  7. #include "Scene/Camera.h"
  8. #include "Scene/Light.h"
  9. #include "Scene/SpotLight.h"
  10. #include "RendererInitializer.h"
  11. namespace R {
  12. //==============================================================================
  13. // init =
  14. //==============================================================================
  15. void Sm::init(const RendererInitializer& initializer)
  16. {
  17. enabled = initializer.is.sm.enabled;
  18. if(!enabled)
  19. {
  20. return;
  21. }
  22. pcfEnabled = initializer.is.sm.pcfEnabled;
  23. bilinearEnabled = initializer.is.sm.bilinearEnabled;
  24. resolution = initializer.is.sm.resolution;
  25. level0Distance = initializer.is.sm.level0Distance;
  26. // Init the levels
  27. initLevel(resolution, level0Distance, bilinearEnabled, levels[0]);
  28. for(uint i = 1; i < levels.size(); i++)
  29. {
  30. initLevel(levels[i - 1].resolution / 2,
  31. levels[i - 1].distance * 2.0,
  32. bilinearEnabled,
  33. levels[i]);
  34. }
  35. }
  36. //==============================================================================
  37. // initLevel =
  38. //==============================================================================
  39. void Sm::initLevel(uint resolution, float distance, bool bilinear, Level& level)
  40. {
  41. level.resolution = resolution;
  42. level.distance = distance;
  43. level.bilinear = bilinear;
  44. try
  45. {
  46. // create FBO
  47. level.fbo.create();
  48. level.fbo.bind();
  49. // texture
  50. Renderer::createFai(level.resolution, level.resolution,
  51. GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT, level.shadowMap);
  52. if(level.bilinear)
  53. {
  54. level.shadowMap.setFiltering(Texture::TFT_LINEAR);
  55. }
  56. else
  57. {
  58. level.shadowMap.setFiltering(Texture::TFT_NEAREST);
  59. }
  60. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
  61. GL_COMPARE_R_TO_TEXTURE);
  62. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  63. /*If you dont want to use the FFP for comparing the shadowmap
  64. (the above two lines) then you can make the comparison
  65. inside the glsl shader. The GL_LEQUAL means that:
  66. shadow = (R <= Dt) ? 1.0 : 0.0; . The R is given by:
  67. R = _tex_coord2.z/_tex_coord2.w; and the
  68. Dt = shadow2D(shadow_depth_map, _shadow_uv).r (see lp_generic.frag).
  69. Hardware filters like GL_LINEAR cannot be applied.*/
  70. // inform the we wont write to color buffers
  71. level.fbo.setNumOfColorAttachements(0);
  72. // attach the texture
  73. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  74. GL_TEXTURE_2D, level.shadowMap.getGlId(), 0);
  75. // test if success
  76. level.fbo.checkIfGood();
  77. // unbind
  78. level.fbo.unbind();
  79. }
  80. catch(std::exception& e)
  81. {
  82. throw EXCEPTION("Cannot create shadowmapping FBO: " + e.what());
  83. }
  84. }
  85. //==============================================================================
  86. // run =
  87. //==============================================================================
  88. void Sm::run(const Light& light, float distance)
  89. {
  90. if(!enabled)
  91. {
  92. return;
  93. }
  94. //
  95. // Determine the level
  96. //
  97. BOOST_FOREACH(Level& level, levels)
  98. {
  99. crntLevel = &level;
  100. if(distance < level.distance)
  101. {
  102. break;
  103. }
  104. }
  105. //
  106. // Render
  107. //
  108. // FBO
  109. crntLevel->fbo.bind();
  110. // set GL
  111. GlStateMachineSingleton::getInstance().setViewport(0, 0,
  112. crntLevel->resolution, crntLevel->resolution);
  113. glClear(GL_DEPTH_BUFFER_BIT);
  114. // disable color & blend & enable depth test
  115. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  116. GlStateMachineSingleton::getInstance().enable(GL_DEPTH_TEST, true);
  117. GlStateMachineSingleton::getInstance().enable(GL_BLEND, false);
  118. // for artifacts
  119. glPolygonOffset(2.0, 2.0); // keep the values as low as possible!!!!
  120. GlStateMachineSingleton::getInstance().enable(GL_POLYGON_OFFSET_FILL);
  121. // render all
  122. BOOST_FOREACH(const RenderableNode* node,
  123. light.getVisibleMsRenderableNodes())
  124. {
  125. switch(light.getType())
  126. {
  127. case Light::LT_SPOT:
  128. {
  129. const SpotLight& sl = static_cast<const SpotLight&>(light);
  130. r.getSceneDrawer().renderRenderableNode(*node, sl.getCamera(),
  131. DEPTH_PASS);
  132. break;
  133. }
  134. default:
  135. ASSERT(0);
  136. }
  137. }
  138. // restore GL
  139. GlStateMachineSingleton::getInstance().disable(GL_POLYGON_OFFSET_FILL);
  140. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  141. // FBO
  142. crntLevel->fbo.unbind();
  143. }
  144. } // end namespace