BsShadowRendering.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsRenderBeastPrerequisites.h"
  5. #include "BsModule.h"
  6. #include "BsMatrix4.h"
  7. #include "BsConvexVolume.h"
  8. #include "BsParamBlocks.h"
  9. #include "BsRendererMaterial.h"
  10. #include "BsTextureAtlasLayout.h"
  11. #include "BsLight.h"
  12. #include "BsLightRendering.h"
  13. namespace bs { namespace ct
  14. {
  15. struct FrameInfo;
  16. class RendererLight;
  17. class RendererScene;
  18. /** @addtogroup RenderBeast
  19. * @{
  20. */
  21. /** Number of frustum splits when rendering cascaded shadow maps. */
  22. const UINT32 NUM_CASCADE_SPLITS = 4;
  23. BS_PARAM_BLOCK_BEGIN(ShadowParamsDef)
  24. BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
  25. BS_PARAM_BLOCK_ENTRY(float, gDepthBias)
  26. BS_PARAM_BLOCK_ENTRY(float, gDepthRange)
  27. BS_PARAM_BLOCK_END
  28. extern ShadowParamsDef gShadowParamsDef;
  29. /** Material used for rendering a single face of a shadow map. */
  30. class ShadowDepthNormalMat : public RendererMaterial<ShadowDepthNormalMat>
  31. {
  32. RMAT_DEF("ShadowDepthNormal.bsl");
  33. public:
  34. ShadowDepthNormalMat();
  35. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  36. void bind(const SPtr<GpuParamBlockBuffer>& shadowParams);
  37. /** Sets a new buffer that determines per-object properties. */
  38. void setPerObjectBuffer(const SPtr<GpuParamBlockBuffer>& perObjectParams);
  39. };
  40. /** Material used for rendering a single face of a shadow map, for a directional light. */
  41. class ShadowDepthDirectionalMat : public RendererMaterial<ShadowDepthDirectionalMat>
  42. {
  43. RMAT_DEF("ShadowDepthDirectional.bsl");
  44. public:
  45. ShadowDepthDirectionalMat();
  46. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  47. void bind(const SPtr<GpuParamBlockBuffer>& shadowParams);
  48. /** Sets a new buffer that determines per-object properties. */
  49. void setPerObjectBuffer(const SPtr<GpuParamBlockBuffer>& perObjectParams);
  50. };
  51. BS_PARAM_BLOCK_BEGIN(ShadowCubeMatricesDef)
  52. BS_PARAM_BLOCK_ENTRY_ARRAY(Matrix4, gFaceVPMatrices, 6)
  53. BS_PARAM_BLOCK_END
  54. extern ShadowCubeMatricesDef gShadowCubeMatricesDef;
  55. BS_PARAM_BLOCK_BEGIN(ShadowCubeMasksDef)
  56. BS_PARAM_BLOCK_ENTRY_ARRAY(int, gFaceMasks, 6)
  57. BS_PARAM_BLOCK_END
  58. extern ShadowCubeMasksDef gShadowCubeMasksDef;
  59. /** Material used for rendering an omni directional cube shadow map. */
  60. class ShadowDepthCubeMat : public RendererMaterial<ShadowDepthCubeMat>
  61. {
  62. RMAT_DEF("ShadowDepthCube.bsl");
  63. public:
  64. ShadowDepthCubeMat();
  65. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  66. void bind(const SPtr<GpuParamBlockBuffer>& shadowParams, const SPtr<GpuParamBlockBuffer>& shadowCubeParams);
  67. /** Sets a new buffer that determines per-object properties. */
  68. void setPerObjectBuffer(const SPtr<GpuParamBlockBuffer>& perObjectParams,
  69. const SPtr<GpuParamBlockBuffer>& shadowCubeMasks);
  70. };
  71. BS_PARAM_BLOCK_BEGIN(ShadowProjectParamsDef)
  72. BS_PARAM_BLOCK_ENTRY(Matrix4, gMixedToShadowSpace)
  73. BS_PARAM_BLOCK_ENTRY(Vector2, gShadowMapSize)
  74. BS_PARAM_BLOCK_ENTRY(Vector2, gShadowMapSizeInv)
  75. BS_PARAM_BLOCK_ENTRY(float, gSoftTransitionScale)
  76. BS_PARAM_BLOCK_ENTRY(float, gFadePercent)
  77. BS_PARAM_BLOCK_ENTRY(float, gFadePlaneDepth)
  78. BS_PARAM_BLOCK_ENTRY(float, gInvFadePlaneRange)
  79. BS_PARAM_BLOCK_END
  80. extern ShadowProjectParamsDef gShadowProjectParamsDef;
  81. /** Material used for projecting depth into a shadow accumulation buffer for non-omnidirectional shadow maps. */
  82. template<int ShadowQuality, bool Directional, bool MSAA>
  83. class ShadowProjectMat : public RendererMaterial<ShadowProjectMat<ShadowQuality, Directional, MSAA>>
  84. {
  85. RMAT_DEF("ShadowProject.bsl");
  86. public:
  87. ShadowProjectMat();
  88. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  89. void bind(const SPtr<Texture>& shadowMap, const SPtr<GpuParamBlockBuffer>& shadowParams,
  90. const SPtr<GpuParamBlockBuffer>& perCamera);
  91. private:
  92. SPtr<SamplerState> mSamplerState;
  93. GBufferParams mGBufferParams;
  94. GpuParamTexture mShadowMapParam;
  95. GpuParamSampState mShadowSamplerParam;
  96. };
  97. BS_PARAM_BLOCK_BEGIN(ShadowProjectOmniParamsDef)
  98. BS_PARAM_BLOCK_ENTRY_ARRAY(Matrix4, gFaceVPMatrices, 6)
  99. BS_PARAM_BLOCK_ENTRY(Vector4, gLightPosAndRadius)
  100. BS_PARAM_BLOCK_ENTRY(float, gInvResolution)
  101. BS_PARAM_BLOCK_ENTRY(float, gFadePercent)
  102. BS_PARAM_BLOCK_ENTRY(float, gDepthBias)
  103. BS_PARAM_BLOCK_END
  104. extern ShadowProjectOmniParamsDef gShadowProjectOmniParamsDef;
  105. /** Material used for projecting depth into a shadow accumulation buffer for omnidirectional shadow maps. */
  106. template<int ShadowQuality, bool MSAA>
  107. class ShadowProjectOmniMat : public RendererMaterial<ShadowProjectOmniMat<ShadowQuality, MSAA>>
  108. {
  109. RMAT_DEF("ShadowProjectOmni.bsl");
  110. public:
  111. ShadowProjectOmniMat();
  112. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  113. void bind(const SPtr<Texture>& shadowMap, const SPtr<GpuParamBlockBuffer>& shadowParams,
  114. const SPtr<GpuParamBlockBuffer>& perCamera);
  115. private:
  116. SPtr<SamplerState> mSamplerState;
  117. GBufferParams mGBufferParams;
  118. GpuParamTexture mShadowMapParam;
  119. GpuParamSampState mShadowSamplerParam;
  120. };
  121. /** Information about a shadow cast from a single light. */
  122. struct ShadowInfo
  123. {
  124. /** Updates normalized area coordinates based on the non-normalized ones and the provided atlas size. */
  125. void updateNormArea(UINT32 atlasSize);
  126. UINT32 lightIdx; /**< Index of the light casting this shadow. */
  127. Rect2I area; /**< Area of the shadow map in pixels, relative to its source texture. */
  128. Rect2 normArea; /**< Normalized shadow map area in [0, 1] range. */
  129. UINT32 textureIdx; /**< Index of the texture the shadow map is stored in. */
  130. /** View-projection matrix from the shadow casters point of view. */
  131. Matrix4 shadowVPTransform;
  132. /** View-projection matrix for each cubemap face, used for omni-directional shadows. */
  133. Matrix4 shadowVPTransforms[6];
  134. /** Determines the fade amount of the shadow, for each view in the scene. */
  135. SmallVector<float, 4> fadePerView;
  136. };
  137. /**
  138. * Contains a texture that serves as an atlas for one or multiple shadow maps. Provides methods for inserting new maps
  139. * in the atlas.
  140. */
  141. class ShadowMapAtlas
  142. {
  143. public:
  144. ShadowMapAtlas(UINT32 size);
  145. ~ShadowMapAtlas();
  146. /**
  147. * Registers a new map in the shadow map atlas. Returns true if the map fits in the atlas, or false otherwise.
  148. * Resets the last used counter to zero.
  149. */
  150. bool addMap(UINT32 size, Rect2I& area, UINT32 border = 4);
  151. /** Clears all shadow maps from the atlas. Increments the last used counter.*/
  152. void clear();
  153. /** Checks have any maps been added to the atlas. */
  154. bool isEmpty() const;
  155. /**
  156. * Returns the value of the last used counter. See addMap() and clear() for information on how the counter is
  157. * incremented/decremented.
  158. */
  159. UINT32 getLastUsedCounter() const { return mLastUsedCounter; }
  160. /** Returns the bindable atlas texture. */
  161. SPtr<Texture> getTexture() const;
  162. /** Returns the render target that allows you to render into the atlas. */
  163. SPtr<RenderTexture> getTarget() const;
  164. private:
  165. SPtr<PooledRenderTexture> mAtlas;
  166. TextureAtlasLayout mLayout;
  167. UINT32 mLastUsedCounter;
  168. };
  169. /** Contains common code for different shadow map types. */
  170. class ShadowMapBase
  171. {
  172. public:
  173. ShadowMapBase(UINT32 size);
  174. virtual ~ShadowMapBase() {}
  175. /** Returns the bindable shadow map texture. */
  176. SPtr<Texture> getTexture() const;
  177. /** Returns the size of a single face of the shadow map texture, in pixels. */
  178. UINT32 getSize() const { return mSize; }
  179. /** Makes the shadow map available for re-use and increments the counter returned by getLastUsedCounter(). */
  180. void clear() { mIsUsed = false; mLastUsedCounter++; }
  181. /** Marks the shadow map as used and resets the last used counter to zero. */
  182. void markAsUsed() { mIsUsed = true; mLastUsedCounter = 0; }
  183. /** Returns true if the object is storing a valid shadow map. */
  184. bool isUsed() const { return mIsUsed; }
  185. /**
  186. * Returns the value of the last used counter. See incrementUseCounter() and markAsUsed() for information on how is
  187. * the counter incremented/decremented.
  188. */
  189. UINT32 getLastUsedCounter() const { return mLastUsedCounter; }
  190. protected:
  191. SPtr<PooledRenderTexture> mShadowMap;
  192. UINT32 mSize;
  193. bool mIsUsed;
  194. UINT32 mLastUsedCounter;
  195. };
  196. /** Contains a cubemap for storing an omnidirectional cubemap. */
  197. class ShadowCubemap : public ShadowMapBase
  198. {
  199. public:
  200. ShadowCubemap(UINT32 size);
  201. ~ShadowCubemap();
  202. /** Returns a render target encompassing all six faces of the shadow cubemap. */
  203. SPtr<RenderTexture> getTarget() const;
  204. };
  205. /** Contains a texture required for rendering cascaded shadow maps. */
  206. class ShadowCascadedMap : public ShadowMapBase
  207. {
  208. public:
  209. ShadowCascadedMap(UINT32 size);
  210. ~ShadowCascadedMap();
  211. /** Returns a render target that allows rendering into a specific cascade of the cascaded shadow map. */
  212. SPtr<RenderTexture> getTarget(UINT32 cascadeIdx) const;
  213. /** Provides information about a shadow for the specified cascade. */
  214. void setShadowInfo(UINT32 cascadeIdx, const ShadowInfo& info) { mShadowInfos[cascadeIdx] = info; }
  215. /** @copydoc setShadowInfo */
  216. const ShadowInfo& getShadowInfo(UINT32 cascadeIdx) const { return mShadowInfos[cascadeIdx]; }
  217. private:
  218. SPtr<RenderTexture> mTargets[NUM_CASCADE_SPLITS];
  219. ShadowInfo mShadowInfos[NUM_CASCADE_SPLITS];
  220. };
  221. /** Provides functionality for rendering shadow maps. */
  222. class ShadowRendering : public Module<ShadowRendering>
  223. {
  224. /** Contains information required for generating a shadow map for a specific light. */
  225. struct ShadowMapOptions
  226. {
  227. UINT32 lightIdx;
  228. UINT32 mapSize;
  229. SmallVector<float, 4> fadePercents;
  230. };
  231. /** Contains references to all shadows cast by a specific light. */
  232. struct LightShadows
  233. {
  234. UINT32 startIdx;
  235. UINT32 numShadows;
  236. };
  237. public:
  238. ShadowRendering(UINT32 shadowMapSize);
  239. /** For each visibile shadow casting light, renders a shadow map from its point of view. */
  240. void renderShadowMaps(RendererScene& scene, const FrameInfo& frameInfo);
  241. /**
  242. * Renders shadow occlusion values for the specified light, into the currently bound render target.
  243. * The system uses shadow maps rendered by renderShadowMaps().
  244. */
  245. void renderShadowOcclusion(const RendererScene& scene, const RendererLight& light, UINT32 viewIdx);
  246. /** Changes the default shadow map size. Will cause all shadow maps to be rebuilt. */
  247. void setShadowMapSize(UINT32 size);
  248. private:
  249. /** Renders cascaded shadow maps for the provided directional light viewed from the provided view. */
  250. void renderCascadedShadowMaps(UINT32 viewIdx, UINT32 lightIdx, RendererScene& scene, const FrameInfo& frameInfo);
  251. /** Renders shadow maps for the provided spot light. */
  252. void renderSpotShadowMap(const RendererLight& light, const ShadowMapOptions& options, RendererScene& scene,
  253. const FrameInfo& frameInfo);
  254. /** Renders shadow maps for the provided radial light. */
  255. void renderRadialShadowMap(const RendererLight& light, const ShadowMapOptions& options, RendererScene& scene,
  256. const FrameInfo& frameInfo);
  257. /**
  258. * Calculates optimal shadow map size, taking into account all views in the scene. Also calculates a fade value
  259. * that can be used for fading out small shadow maps.
  260. *
  261. * @param[in] light Light for which to calculate the shadow map properties. Cannot be a directional light.
  262. * @param[in] scene Scene information containing all the views the light can be seen through.
  263. * @param[out] size Optimal size of the shadow map, in pixels.
  264. * @param[out] fadePercents Value in range [0, 1] determining how much should the shadow map be faded out. Each
  265. * entry corresponds to a single view.
  266. * @param[out] maxFadePercent Maximum value in the @p fadePercents array.
  267. */
  268. void calcShadowMapProperties(const RendererLight& light, RendererScene& scene, UINT32& size,
  269. SmallVector<float, 4>& fadePercents, float& maxFadePercent) const;
  270. /**
  271. * Generates a frustum for a single cascade of a cascaded shadow map. Also outputs spherical bounds of the
  272. * split view frustum.
  273. *
  274. * @param[in] view View whose frustum to split.
  275. * @param[in] lightDir Direction of the light for which we're generating the shadow map.
  276. * @param[in] cascade Index of the cascade to generate the frustum for.
  277. * @param[in] numCascades Maximum number of cascades in the cascaded shadow map. Must be greater than zero.
  278. * @param[out] outBounds Spherical bounds of the split view frustum.
  279. * @return Convex volume covering the area of the split view frustum visible from the light.
  280. */
  281. static ConvexVolume getCSMSplitFrustum(const RendererView& view, const Vector3& lightDir, UINT32 cascade,
  282. UINT32 numCascades, Sphere& outBounds);
  283. /**
  284. * Finds the distance (along the view direction) of the frustum split for the specified index. Used for cascaded
  285. * shadow maps.
  286. *
  287. * @param[in] view View whose frustum to split.
  288. * @param[in] index Index of the split. 0 = near plane.
  289. * @param[in] numCascades Maximum number of cascades in the cascaded shadow map. Must be greater than zero
  290. * and greater or equal to @p index.
  291. * @return Distance to the split position along the view direction.
  292. */
  293. static float getCSMSplitDistance(const RendererView& view, UINT32 index, UINT32 numCascades);
  294. /**
  295. * Calculates a bias that can be applied when rendering shadow maps, in order to reduce shadow artifacts.
  296. *
  297. * @param[in] light Light to calculate the depth bias for.
  298. * @param[in] depthRange Range of depths (distance between near and far planes) covered by the shadow.
  299. * @param[in] mapSize Size of the shadow map, in pixels.
  300. * @return Depth bias that can be passed to shadow depth rendering shader.
  301. */
  302. static float getDepthBias(const Light& light, float depthRange, UINT32 mapSize);
  303. /** Size of a single shadow map atlas, in pixels. */
  304. static const UINT32 MAX_ATLAS_SIZE;
  305. /** Determines how long will an unused shadow map atlas stay allocated, in frames. */
  306. static const UINT32 MAX_UNUSED_FRAMES;
  307. /** Determines the minimal resolution of a shadow map. */
  308. static const UINT32 MIN_SHADOW_MAP_SIZE;
  309. /** Determines the resolution at which shadow maps begin fading out. */
  310. static const UINT32 SHADOW_MAP_FADE_SIZE;
  311. /** Size of the border of a shadow map in a shadow map atlas, in pixels. */
  312. static const UINT32 SHADOW_MAP_BORDER;
  313. ShadowDepthNormalMat mDepthNormalMat;
  314. ShadowDepthCubeMat mDepthCubeMat;
  315. ShadowDepthDirectionalMat mDepthDirectionalMat;
  316. UINT32 mShadowMapSize;
  317. Vector<ShadowMapAtlas> mDynamicShadowMaps;
  318. Vector<ShadowCascadedMap> mCascadedShadowMaps;
  319. Vector<ShadowCubemap> mShadowCubemaps;
  320. Vector<ShadowInfo> mShadowInfos;
  321. Vector<LightShadows> mSpotLightShadows;
  322. Vector<LightShadows> mRadialLightShadows;
  323. Vector<UINT32> mDirectionalLightShadows;
  324. Vector<bool> mRenderableVisibility; // Transient
  325. Vector<ShadowMapOptions> mSpotLightShadowOptions; // Transient
  326. Vector<ShadowMapOptions> mRadialLightShadowOptions; // Transient
  327. };
  328. /* @} */
  329. }}