Sm.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "anki/renderer/Sm.h"
  6. #include "anki/renderer/Renderer.h"
  7. #include "anki/core/App.h"
  8. #include "anki/core/Counters.h"
  9. #include "anki/scene/SceneGraph.h"
  10. #include "anki/scene/Camera.h"
  11. #include "anki/scene/Light.h"
  12. #include "anki/misc/ConfigSet.h"
  13. namespace anki {
  14. //==============================================================================
  15. const PixelFormat Sm::DEPTH_RT_PIXEL_FORMAT(
  16. ComponentFormat::D16, TransformFormat::FLOAT);
  17. //==============================================================================
  18. Error Sm::init(const ConfigSet& config)
  19. {
  20. m_enabled = config.getNumber("is.sm.enabled");
  21. if(!m_enabled)
  22. {
  23. return ErrorCode::NONE;
  24. }
  25. m_poissonEnabled = config.getNumber("is.sm.poissonEnabled");
  26. m_bilinearEnabled = config.getNumber("is.sm.bilinearEnabled");
  27. m_resolution = config.getNumber("is.sm.resolution");
  28. //
  29. // Init the shadowmaps
  30. //
  31. if(config.getNumber("is.sm.maxLights") > MAX_SHADOW_CASTERS)
  32. {
  33. ANKI_LOGE("Too many shadow casters");
  34. return ErrorCode::FUNCTION_FAILED;
  35. }
  36. // Create shadowmaps array
  37. TextureInitializer sminit;
  38. sminit.m_type = TextureType::_2D_ARRAY;
  39. sminit.m_width = m_resolution;
  40. sminit.m_height = m_resolution;
  41. sminit.m_depth = config.getNumber("is.sm.maxLights");
  42. sminit.m_format = DEPTH_RT_PIXEL_FORMAT;
  43. sminit.m_mipmapsCount = 1;
  44. sminit.m_sampling.m_minMagFilter = m_bilinearEnabled
  45. ? SamplingFilter::LINEAR
  46. : SamplingFilter::NEAREST;
  47. sminit.m_sampling.m_compareOperation = CompareOperation::LESS_EQUAL;
  48. m_spotTexArray = getGrManager().newInstance<Texture>(sminit);
  49. sminit.m_type = TextureType::CUBE_ARRAY;
  50. m_omniTexArray = getGrManager().newInstance<Texture>(sminit);
  51. // Init 2D layers
  52. m_spots.create(getAllocator(), config.getNumber("is.sm.maxLights"));
  53. FramebufferInitializer fbInit;
  54. fbInit.m_depthStencilAttachment.m_texture = m_spotTexArray;
  55. fbInit.m_depthStencilAttachment.m_loadOperation =
  56. AttachmentLoadOperation::CLEAR;
  57. fbInit.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0;
  58. U layer = 0;
  59. for(ShadowmapSpot& sm : m_spots)
  60. {
  61. sm.m_layerId = layer;
  62. fbInit.m_depthStencilAttachment.m_layer = layer;
  63. sm.m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
  64. ++layer;
  65. }
  66. // Init cube layers
  67. m_omnis.create(getAllocator(), config.getNumber("is.sm.maxLights"));
  68. fbInit.m_depthStencilAttachment.m_texture = m_omniTexArray;
  69. layer = 0;
  70. for(ShadowmapOmni& sm : m_omnis)
  71. {
  72. sm.m_layerId = layer;
  73. for(U i = 0; i < 6; ++i)
  74. {
  75. fbInit.m_depthStencilAttachment.m_layer = layer * 6 + i;
  76. sm.m_fb[i] = getGrManager().newInstance<Framebuffer>(fbInit);
  77. }
  78. ++layer;
  79. }
  80. return ErrorCode::NONE;
  81. }
  82. //==============================================================================
  83. Error Sm::run(SArray<SceneNode*> spotShadowCasters,
  84. SArray<SceneNode*> omniShadowCasters, CommandBufferPtr& cmdBuff)
  85. {
  86. ANKI_ASSERT(m_enabled);
  87. if(omniShadowCasters.getSize() > m_omnis.getSize()
  88. || spotShadowCasters.getSize() > m_spots.getSize())
  89. {
  90. ANKI_LOGW("Too many shadow casters");
  91. }
  92. // render all
  93. for(SceneNode* node : spotShadowCasters)
  94. {
  95. ANKI_CHECK(doSpotLight(*node, cmdBuff));
  96. }
  97. for(SceneNode* node : omniShadowCasters)
  98. {
  99. ANKI_CHECK(doOmniLight(*node, cmdBuff));
  100. }
  101. return ErrorCode::NONE;
  102. }
  103. //==============================================================================
  104. template<typename TShadowmap, typename TContainer>
  105. void Sm::bestCandidate(SceneNode& light, TContainer& arr, TShadowmap*& out)
  106. {
  107. // Allready there
  108. for(TShadowmap& sm : arr)
  109. {
  110. if(&light == sm.m_light)
  111. {
  112. out = &sm;
  113. return;
  114. }
  115. }
  116. // Find a null
  117. for(TShadowmap& sm : arr)
  118. {
  119. if(sm.m_light == nullptr)
  120. {
  121. sm.m_light = &light;
  122. sm.m_timestamp = 0;
  123. out = &sm;
  124. return;
  125. }
  126. }
  127. // Find an old and replace it
  128. TShadowmap* sm = &arr[0];
  129. for(U i = 1; i < arr.getSize(); i++)
  130. {
  131. if(arr[i].m_timestamp < sm->m_timestamp)
  132. {
  133. sm = &arr[i];
  134. }
  135. }
  136. sm->m_light = &light;
  137. sm->m_timestamp = 0;
  138. out = sm;
  139. }
  140. //==============================================================================
  141. Bool Sm::skip(SceneNode& light, ShadowmapBase& sm)
  142. {
  143. MoveComponent* movc =
  144. light.tryGetComponent<MoveComponent>();
  145. Timestamp lastUpdate = movc->getTimestamp();
  146. Error err = light.iterateComponentsOfType<FrustumComponent>(
  147. [&](FrustumComponent& fr)
  148. {
  149. lastUpdate = max(lastUpdate, fr.getTimestamp());
  150. VisibilityTestResults& vi = fr.getVisibilityTestResults();
  151. lastUpdate = max(lastUpdate, vi.getShapeUpdateTimestamp());
  152. return ErrorCode::NONE;
  153. });
  154. (void)err;
  155. Bool shouldUpdate = lastUpdate >= sm.m_timestamp;
  156. if(shouldUpdate)
  157. {
  158. sm.m_timestamp = getGlobalTimestamp();
  159. LightComponent& lcomp = light.getComponent<LightComponent>();
  160. lcomp.setShadowMapIndex(sm.m_layerId);
  161. }
  162. return !shouldUpdate;
  163. }
  164. //==============================================================================
  165. Error Sm::doSpotLight(SceneNode& light, CommandBufferPtr& cmdBuff)
  166. {
  167. ShadowmapSpot* sm;
  168. bestCandidate(light, m_spots, sm);
  169. if(skip(light, *sm))
  170. {
  171. return ErrorCode::NONE;
  172. }
  173. cmdBuff->bindFramebuffer(sm->m_fb);
  174. cmdBuff->setViewport(0, 0, m_resolution, m_resolution);
  175. FrustumComponent& fr = light.getComponent<FrustumComponent>();
  176. SArray<CommandBufferPtr> cmdbs(&cmdBuff, 1);
  177. ANKI_CHECK(m_r->getSceneDrawer().render(
  178. fr, RenderingStage::MATERIAL, Pass::SM, cmdbs));
  179. ANKI_COUNTER_INC(RENDERER_SHADOW_PASSES, U64(1));
  180. return ErrorCode::NONE;
  181. }
  182. //==============================================================================
  183. Error Sm::doOmniLight(SceneNode& light, CommandBufferPtr& cmdBuff)
  184. {
  185. ShadowmapOmni* sm;
  186. bestCandidate(light, m_omnis, sm);
  187. if(skip(light, *sm))
  188. {
  189. return ErrorCode::NONE;
  190. }
  191. cmdBuff->setViewport(0, 0, m_resolution, m_resolution);
  192. U frCount = 0;
  193. Error err = light.iterateComponentsOfType<FrustumComponent>(
  194. [&](FrustumComponent& fr) -> Error
  195. {
  196. cmdBuff->bindFramebuffer(sm->m_fb[frCount]);
  197. SArray<CommandBufferPtr> cmdbs(&cmdBuff, 1);
  198. ANKI_CHECK(m_r->getSceneDrawer().render(
  199. fr, RenderingStage::MATERIAL, Pass::SM, cmdbs));
  200. ++frCount;
  201. return ErrorCode::NONE;
  202. });
  203. ANKI_COUNTER_INC(RENDERER_SHADOW_PASSES, U64(6));
  204. return err;
  205. }
  206. } // end namespace anki