Sm.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include <boost/foreach.hpp>
  2. #include "anki/renderer/Sm.h"
  3. #include "anki/renderer/Renderer.h"
  4. #include "anki/core/App.h"
  5. #include "anki/scene/Scene.h"
  6. #include "anki/resource/LightRsrc.h"
  7. #include "anki/scene/Camera.h"
  8. #include "anki/scene/Light.h"
  9. #include "anki/scene/SpotLight.h"
  10. #include "anki/renderer/RendererInitializer.h"
  11. namespace anki {
  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 ANKI_EXCEPTION("Cannot create shadowmapping "
  83. "FBO") << e;
  84. }
  85. }
  86. //==============================================================================
  87. // run =
  88. //==============================================================================
  89. void Sm::run(const Light& light, float distance)
  90. {
  91. if(!enabled)
  92. {
  93. return;
  94. }
  95. ANKI_ASSERT(light.getVisibleMsRenderableNodes().size() > 0);
  96. //
  97. // Determine the level
  98. //
  99. BOOST_FOREACH(Level& level, levels)
  100. {
  101. crntLevel = &level;
  102. if(distance < level.distance)
  103. {
  104. break;
  105. }
  106. }
  107. //
  108. // Render
  109. //
  110. // FBO
  111. crntLevel->fbo.bind();
  112. // set GL
  113. GlStateMachineSingleton::get().setViewport(0, 0,
  114. crntLevel->resolution, crntLevel->resolution);
  115. glClear(GL_DEPTH_BUFFER_BIT);
  116. // disable color & blend & enable depth test
  117. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  118. GlStateMachineSingleton::get().enable(GL_DEPTH_TEST, true);
  119. GlStateMachineSingleton::get().enable(GL_BLEND, false);
  120. // for artifacts
  121. glPolygonOffset(2.0, 2.0); // keep the values as low as possible!!!!
  122. GlStateMachineSingleton::get().enable(GL_POLYGON_OFFSET_FILL);
  123. // render all
  124. BOOST_FOREACH(const RenderableNode* node,
  125. light.getVisibleMsRenderableNodes())
  126. {
  127. switch(light.getLightType())
  128. {
  129. case Light::LT_SPOT:
  130. {
  131. const SpotLight& sl = static_cast<const SpotLight&>(light);
  132. r.getSceneDrawer().renderRenderableNode(*node, sl.getCamera(),
  133. PassLevelKey(1, 0));
  134. break;
  135. }
  136. default:
  137. ANKI_ASSERT(0);
  138. }
  139. }
  140. // restore GL
  141. GlStateMachineSingleton::get().disable(GL_POLYGON_OFFSET_FILL);
  142. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  143. // FBO
  144. crntLevel->fbo.unbind();
  145. }
  146. } // end namespace