Sm.cpp 4.3 KB

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