BsShadowRendering.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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 "Utility/BsModule.h"
  6. #include "Math/BsMatrix4.h"
  7. #include "Math/BsConvexVolume.h"
  8. #include "Renderer/BsParamBlocks.h"
  9. #include "Renderer/BsRendererMaterial.h"
  10. #include "Image/BsTextureAtlasLayout.h"
  11. #include "Renderer/BsLight.h"
  12. #include "BsLightRendering.h"
  13. namespace bs { namespace ct
  14. {
  15. struct FrameInfo;
  16. class RendererLight;
  17. class RendererScene;
  18. struct ShadowInfo;
  19. /** @addtogroup RenderBeast
  20. * @{
  21. */
  22. BS_PARAM_BLOCK_BEGIN(ShadowParamsDef)
  23. BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
  24. BS_PARAM_BLOCK_ENTRY(Vector2, gNDCZToDeviceZ)
  25. BS_PARAM_BLOCK_ENTRY(float, gDepthBias)
  26. BS_PARAM_BLOCK_ENTRY(float, gInvDepthRange)
  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. /** Helper method used for initializing variations of this material. */
  34. template<bool skinned, bool morph>
  35. static const ShaderVariation& getVariation()
  36. {
  37. static ShaderVariation variation = ShaderVariation(
  38. Vector<ShaderVariation::Param>{
  39. ShaderVariation::Param("SKINNED", skinned),
  40. ShaderVariation::Param("MORPH", morph)
  41. });
  42. return variation;
  43. }
  44. public:
  45. ShadowDepthNormalMat();
  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. * Returns the material variation matching the provided parameters.
  52. *
  53. * @param[in] skinned True if the shadow caster supports bone animation.
  54. * @param[in] morph True if the shadow caster supports morph shape animation.
  55. */
  56. static ShadowDepthNormalMat* getVariation(bool skinned, bool morph);
  57. };
  58. /** Material used for rendering a single face of a shadow map, for a directional light. */
  59. class ShadowDepthDirectionalMat : public RendererMaterial<ShadowDepthDirectionalMat>
  60. {
  61. RMAT_DEF("ShadowDepthDirectional.bsl");
  62. /** Helper method used for initializing variations of this material. */
  63. template<bool skinned, bool morph>
  64. static const ShaderVariation& getVariation()
  65. {
  66. static ShaderVariation variation = ShaderVariation(
  67. Vector<ShaderVariation::Param>{
  68. ShaderVariation::Param("SKINNED", skinned),
  69. ShaderVariation::Param("MORPH", morph)
  70. });
  71. return variation;
  72. }
  73. public:
  74. ShadowDepthDirectionalMat();
  75. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  76. void bind(const SPtr<GpuParamBlockBuffer>& shadowParams);
  77. /** Sets a new buffer that determines per-object properties. */
  78. void setPerObjectBuffer(const SPtr<GpuParamBlockBuffer>& perObjectParams);
  79. /**
  80. * Returns the material variation matching the provided parameters.
  81. *
  82. * @param[in] skinned True if the shadow caster supports bone animation.
  83. * @param[in] morph True if the shadow caster supports morph shape animation.
  84. */
  85. static ShadowDepthDirectionalMat* getVariation(bool skinned, bool morph);
  86. };
  87. BS_PARAM_BLOCK_BEGIN(ShadowCubeMatricesDef)
  88. BS_PARAM_BLOCK_ENTRY_ARRAY(Matrix4, gFaceVPMatrices, 6)
  89. BS_PARAM_BLOCK_END
  90. extern ShadowCubeMatricesDef gShadowCubeMatricesDef;
  91. BS_PARAM_BLOCK_BEGIN(ShadowCubeMasksDef)
  92. BS_PARAM_BLOCK_ENTRY_ARRAY(int, gFaceMasks, 6)
  93. BS_PARAM_BLOCK_END
  94. extern ShadowCubeMasksDef gShadowCubeMasksDef;
  95. /** Material used for rendering an omni directional cube shadow map. */
  96. class ShadowDepthCubeMat : public RendererMaterial<ShadowDepthCubeMat>
  97. {
  98. RMAT_DEF("ShadowDepthCube.bsl");
  99. /** Helper method used for initializing variations of this material. */
  100. template<bool skinned, bool morph>
  101. static const ShaderVariation& getVariation()
  102. {
  103. static ShaderVariation variation = ShaderVariation(
  104. Vector<ShaderVariation::Param>{
  105. ShaderVariation::Param("SKINNED", skinned),
  106. ShaderVariation::Param("MORPH", morph)
  107. });
  108. return variation;
  109. }
  110. public:
  111. ShadowDepthCubeMat();
  112. /** Binds the material to the pipeline, ready to be used on subsequent draw calls. */
  113. void bind(const SPtr<GpuParamBlockBuffer>& shadowParams, const SPtr<GpuParamBlockBuffer>& shadowCubeParams);
  114. /** Sets a new buffer that determines per-object properties. */
  115. void setPerObjectBuffer(const SPtr<GpuParamBlockBuffer>& perObjectParams,
  116. const SPtr<GpuParamBlockBuffer>& shadowCubeMasks);
  117. /**
  118. * Returns the material variation matching the provided parameters.
  119. *
  120. * @param[in] skinned True if the shadow caster supports bone animation.
  121. * @param[in] morph True if the shadow caster supports morph shape animation.
  122. */
  123. static ShadowDepthCubeMat* getVariation(bool skinned, bool morph);
  124. };
  125. BS_PARAM_BLOCK_BEGIN(ShadowProjectVertParamsDef)
  126. BS_PARAM_BLOCK_ENTRY(Vector4, gPositionAndScale)
  127. BS_PARAM_BLOCK_END
  128. extern ShadowProjectVertParamsDef gShadowProjectVertParamsDef;
  129. /** Material used for populating the stencil buffer when projecting non-omnidirectional shadows. */
  130. class ShadowProjectStencilMat : public RendererMaterial<ShadowProjectStencilMat>
  131. {
  132. RMAT_DEF("ShadowProjectStencil.bsl");
  133. /** Helper method used for initializing variations of this material. */
  134. template<bool directional, bool useZFailStencil>
  135. static const ShaderVariation& getVariation()
  136. {
  137. static ShaderVariation variation = ShaderVariation(
  138. Vector<ShaderVariation::Param>{
  139. ShaderVariation::Param("NEEDS_TRANSFORM", !directional),
  140. ShaderVariation::Param("USE_ZFAIL_STENCIL", useZFailStencil)
  141. });
  142. return variation;
  143. };
  144. public:
  145. ShadowProjectStencilMat();
  146. /** Binds the material and its parameters to the pipeline. */
  147. void bind(const SPtr<GpuParamBlockBuffer>& perCamera);
  148. /** Returns the material variation matching the provided parameters.
  149. *
  150. * @param[in] directional Set to true if shadows from a directional light are being rendered.
  151. * @param[in] useZFailStencil If true the material will use z-fail operation to modify the stencil buffer. If
  152. * false z-pass will be used instead. Z-pass is a more performant alternative as it
  153. * doesn't disable hi-z optimization, but it cannot handle the case when the viewer is
  154. * inside the drawn geometry.
  155. */
  156. static ShadowProjectStencilMat* getVariation(bool directional, bool useZFailStencil);
  157. private:
  158. SPtr<GpuParamBlockBuffer> mVertParams;
  159. };
  160. /** Common parameters used by the shadow projection materials. */
  161. struct ShadowProjectParams
  162. {
  163. ShadowProjectParams(const Light& light, const SPtr<Texture>& shadowMap,
  164. const SPtr<GpuParamBlockBuffer>& shadowParams, const SPtr<GpuParamBlockBuffer>& perCameraParams,
  165. GBufferTextures gbuffer)
  166. : light(light), shadowMap(shadowMap), shadowParams(shadowParams), perCamera(perCameraParams), gbuffer(gbuffer)
  167. { }
  168. /** Light which is casting the shadow. */
  169. const Light& light;
  170. /** Texture containing the shadow map. */
  171. const SPtr<Texture>& shadowMap;
  172. /** Parameter block containing parameters specific for shadow projection. */
  173. const SPtr<GpuParamBlockBuffer> shadowParams;
  174. /** Parameter block containing parameters specific to this view. */
  175. const SPtr<GpuParamBlockBuffer>& perCamera;
  176. /** Contains the GBuffer textures. */
  177. GBufferTextures gbuffer;
  178. };
  179. BS_PARAM_BLOCK_BEGIN(ShadowProjectParamsDef)
  180. BS_PARAM_BLOCK_ENTRY(Matrix4, gMixedToShadowSpace)
  181. BS_PARAM_BLOCK_ENTRY(Vector2, gShadowMapSize)
  182. BS_PARAM_BLOCK_ENTRY(Vector2, gShadowMapSizeInv)
  183. BS_PARAM_BLOCK_ENTRY(float, gSoftTransitionScale)
  184. BS_PARAM_BLOCK_ENTRY(float, gFadePercent)
  185. BS_PARAM_BLOCK_ENTRY(float, gFadePlaneDepth)
  186. BS_PARAM_BLOCK_ENTRY(float, gInvFadePlaneRange)
  187. BS_PARAM_BLOCK_ENTRY(float, gFace)
  188. BS_PARAM_BLOCK_END
  189. extern ShadowProjectParamsDef gShadowProjectParamsDef;
  190. /** Material used for projecting depth into a shadow accumulation buffer for non-omnidirectional shadow maps. */
  191. class ShadowProjectMat : public RendererMaterial<ShadowProjectMat>
  192. {
  193. RMAT_DEF("ShadowProject.bsl");
  194. /** Helper method used for initializing variations of this material. */
  195. template<UINT32 quality, bool directional, bool MSAA>
  196. static const ShaderVariation& getVariation()
  197. {
  198. static ShaderVariation variation = ShaderVariation(
  199. Vector<ShaderVariation::Param>{
  200. ShaderVariation::Param("SHADOW_QUALITY", quality),
  201. ShaderVariation::Param("CASCADING", directional),
  202. ShaderVariation::Param("NEEDS_TRANSFORM", !directional),
  203. ShaderVariation::Param("MSAA_COUNT", MSAA ? 2 : 1)
  204. });
  205. return variation;
  206. };
  207. public:
  208. ShadowProjectMat();
  209. /** Binds the material and its parameters to the pipeline. */
  210. void bind(const ShadowProjectParams& params);
  211. /** Returns the material variation matching the provided parameters.
  212. *
  213. * @param[in] quality Quality of the shadow filtering to use. In range [1, 4].
  214. * @param[in] directional True if rendering a shadow from a directional light.
  215. * @param[in] MSAA True if the GBuffer contains per-sample data.
  216. */
  217. static ShadowProjectMat* getVariation(UINT32 quality, bool directional, bool MSAA);
  218. private:
  219. SPtr<SamplerState> mSamplerState;
  220. SPtr<GpuParamBlockBuffer> mVertParams;
  221. GBufferParams mGBufferParams;
  222. GpuParamTexture mShadowMapParam;
  223. GpuParamSampState mShadowSamplerParam;
  224. };
  225. BS_PARAM_BLOCK_BEGIN(ShadowProjectOmniParamsDef)
  226. BS_PARAM_BLOCK_ENTRY_ARRAY(Matrix4, gFaceVPMatrices, 6)
  227. BS_PARAM_BLOCK_ENTRY(Vector4, gLightPosAndRadius)
  228. BS_PARAM_BLOCK_ENTRY(float, gInvResolution)
  229. BS_PARAM_BLOCK_ENTRY(float, gFadePercent)
  230. BS_PARAM_BLOCK_ENTRY(float, gDepthBias)
  231. BS_PARAM_BLOCK_END
  232. extern ShadowProjectOmniParamsDef gShadowProjectOmniParamsDef;
  233. /** Material used for projecting depth into a shadow accumulation buffer for omnidirectional shadow maps. */
  234. class ShadowProjectOmniMat : public RendererMaterial<ShadowProjectOmniMat>
  235. {
  236. RMAT_DEF("ShadowProjectOmni.bsl");
  237. /** Helper method used for initializing variations of this material. */
  238. template<UINT32 quality, bool inside, bool MSAA>
  239. static const ShaderVariation& getVariation()
  240. {
  241. static ShaderVariation variation = ShaderVariation(
  242. Vector<ShaderVariation::Param>{
  243. ShaderVariation::Param("SHADOW_QUALITY", quality),
  244. ShaderVariation::Param("VIEWER_INSIDE_VOLUME", inside),
  245. ShaderVariation::Param("NEEDS_TRANSFORM", true),
  246. ShaderVariation::Param("MSAA_COUNT", MSAA ? 2 : 1)
  247. });
  248. return variation;
  249. };
  250. public:
  251. ShadowProjectOmniMat();
  252. /** Binds the material and its parameters to the pipeline. */
  253. void bind(const ShadowProjectParams& params);
  254. /** Returns the material variation matching the provided parameters.
  255. *
  256. * @param[in] quality Quality of the shadow filtering to use. In range [1, 4].
  257. * @param[in] inside True if the viewer is inside the light volume.
  258. * @param[in] MSAA True if the GBuffer contains per-sample data.
  259. */
  260. static ShadowProjectOmniMat* getVariation(UINT32 quality, bool inside, bool MSAA);
  261. private:
  262. SPtr<SamplerState> mSamplerState;
  263. SPtr<GpuParamBlockBuffer> mVertParams;
  264. GBufferParams mGBufferParams;
  265. GpuParamTexture mShadowMapParam;
  266. GpuParamSampState mShadowSamplerParam;
  267. };
  268. /** Pixel format used for rendering and storing shadow maps. */
  269. const PixelFormat SHADOW_MAP_FORMAT = PF_D16;
  270. /** Information about a shadow cast from a single light. */
  271. struct ShadowInfo
  272. {
  273. /** Updates normalized area coordinates based on the non-normalized ones and the provided atlas size. */
  274. void updateNormArea(UINT32 atlasSize);
  275. UINT32 lightIdx; /**< Index of the light casting this shadow. */
  276. Rect2I area; /**< Area of the shadow map in pixels, relative to its source texture. */
  277. Rect2 normArea; /**< Normalized shadow map area in [0, 1] range. */
  278. UINT32 textureIdx; /**< Index of the texture the shadow map is stored in. */
  279. float depthNear; /**< Distance to the near plane. */
  280. float depthFar; /**< Distance to the far plane. */
  281. float depthFade; /**< Distance to the plane at which to start fading out the shadows (only for CSM). */
  282. float fadeRange; /**< Distance from the fade plane to the far plane (only for CSM). */
  283. float depthBias; /**< Bias used to reduce shadow acne. */
  284. float depthRange; /**< Length of the range covered by the shadow caster volume. */
  285. UINT32 cascadeIdx; /**< Index of a cascade. Only relevant for CSM. */
  286. /** View-projection matrix from the shadow casters point of view. */
  287. Matrix4 shadowVPTransform;
  288. /** View-projection matrix for each cubemap face, used for omni-directional shadows. */
  289. Matrix4 shadowVPTransforms[6];
  290. /** Bounds of the geometry the shadow is being applied on. */
  291. Sphere subjectBounds;
  292. /** Determines the fade amount of the shadow, for each view in the scene. */
  293. SmallVector<float, 6> fadePerView;
  294. };
  295. /**
  296. * Contains a texture that serves as an atlas for one or multiple shadow maps. Provides methods for inserting new maps
  297. * in the atlas.
  298. */
  299. class ShadowMapAtlas
  300. {
  301. public:
  302. ShadowMapAtlas(UINT32 size);
  303. /**
  304. * Registers a new map in the shadow map atlas. Returns true if the map fits in the atlas, or false otherwise.
  305. * Resets the last used counter to zero.
  306. */
  307. bool addMap(UINT32 size, Rect2I& area, UINT32 border = 4);
  308. /** Clears all shadow maps from the atlas. Increments the last used counter.*/
  309. void clear();
  310. /** Checks have any maps been added to the atlas. */
  311. bool isEmpty() const;
  312. /**
  313. * Returns the value of the last used counter. See addMap() and clear() for information on how the counter is
  314. * incremented/decremented.
  315. */
  316. UINT32 getLastUsedCounter() const { return mLastUsedCounter; }
  317. /** Returns the bindable atlas texture. */
  318. SPtr<Texture> getTexture() const;
  319. /** Returns the render target that allows you to render into the atlas. */
  320. SPtr<RenderTexture> getTarget() const;
  321. private:
  322. SPtr<PooledRenderTexture> mAtlas;
  323. TextureAtlasLayout mLayout;
  324. UINT32 mLastUsedCounter;
  325. };
  326. /** Contains common code for different shadow map types. */
  327. class ShadowMapBase
  328. {
  329. public:
  330. ShadowMapBase(UINT32 size);
  331. virtual ~ShadowMapBase() {}
  332. /** Returns the bindable shadow map texture. */
  333. SPtr<Texture> getTexture() const;
  334. /** Returns the size of a single face of the shadow map texture, in pixels. */
  335. UINT32 getSize() const { return mSize; }
  336. /** Makes the shadow map available for re-use and increments the counter returned by getLastUsedCounter(). */
  337. void clear() { mIsUsed = false; mLastUsedCounter++; }
  338. /** Marks the shadow map as used and resets the last used counter to zero. */
  339. void markAsUsed() { mIsUsed = true; mLastUsedCounter = 0; }
  340. /** Returns true if the object is storing a valid shadow map. */
  341. bool isUsed() const { return mIsUsed; }
  342. /**
  343. * Returns the value of the last used counter. See incrementUseCounter() and markAsUsed() for information on how is
  344. * the counter incremented/decremented.
  345. */
  346. UINT32 getLastUsedCounter() const { return mLastUsedCounter; }
  347. protected:
  348. SPtr<PooledRenderTexture> mShadowMap;
  349. UINT32 mSize;
  350. bool mIsUsed;
  351. UINT32 mLastUsedCounter;
  352. };
  353. /** Contains a cubemap for storing an omnidirectional cubemap. */
  354. class ShadowCubemap : public ShadowMapBase
  355. {
  356. public:
  357. ShadowCubemap(UINT32 size);
  358. /** Returns a render target encompassing all six faces of the shadow cubemap. */
  359. SPtr<RenderTexture> getTarget() const;
  360. };
  361. /** Contains a texture required for rendering cascaded shadow maps. */
  362. class ShadowCascadedMap : public ShadowMapBase
  363. {
  364. public:
  365. ShadowCascadedMap(UINT32 size, UINT32 numCascades);
  366. /** Returns the total number of cascades in the cascade shadow map. */
  367. UINT32 getNumCascades() const { return mNumCascades; }
  368. /** Returns a render target that allows rendering into a specific cascade of the cascaded shadow map. */
  369. SPtr<RenderTexture> getTarget(UINT32 cascadeIdx) const;
  370. /** Provides information about a shadow for the specified cascade. */
  371. void setShadowInfo(UINT32 cascadeIdx, const ShadowInfo& info) { mShadowInfos[cascadeIdx] = info; }
  372. /** @copydoc setShadowInfo */
  373. const ShadowInfo& getShadowInfo(UINT32 cascadeIdx) const { return mShadowInfos[cascadeIdx]; }
  374. private:
  375. UINT32 mNumCascades;
  376. Vector<SPtr<RenderTexture>> mTargets;
  377. Vector<ShadowInfo> mShadowInfos;
  378. };
  379. /** Provides functionality for rendering shadow maps. */
  380. class ShadowRendering
  381. {
  382. /** Contains information required for generating a shadow map for a specific light. */
  383. struct ShadowMapOptions
  384. {
  385. UINT32 lightIdx;
  386. UINT32 mapSize;
  387. SmallVector<float, 6> fadePercents;
  388. };
  389. /** Contains references to all shadows cast by a specific light. */
  390. struct LightShadows
  391. {
  392. UINT32 startIdx = 0;
  393. UINT32 numShadows = 0;
  394. };
  395. /** Contains references to all shadows cast by a specific light, per view. */
  396. struct PerViewLightShadows
  397. {
  398. SmallVector<LightShadows, 6> viewShadows;
  399. };
  400. public:
  401. ShadowRendering(UINT32 shadowMapSize);
  402. /** For each visible shadow casting light, renders a shadow map from its point of view. */
  403. void renderShadowMaps(RendererScene& scene, const RendererViewGroup& viewGroup, const FrameInfo& frameInfo);
  404. /**
  405. * Renders shadow occlusion values for the specified light, through the provided view, into the currently bound
  406. * render target. The system uses shadow maps rendered by renderShadowMaps().
  407. */
  408. void renderShadowOcclusion(const RendererView& view, const RendererLight& light, GBufferTextures gbuffer) const;
  409. /** Changes the default shadow map size. Will cause all shadow maps to be rebuilt. */
  410. void setShadowMapSize(UINT32 size);
  411. private:
  412. /** Renders cascaded shadow maps for the provided directional light viewed from the provided view. */
  413. void renderCascadedShadowMaps(const RendererView& view, UINT32 lightIdx, RendererScene& scene,
  414. const FrameInfo& frameInfo);
  415. /** Renders shadow maps for the provided spot light. */
  416. void renderSpotShadowMap(const RendererLight& light, const ShadowMapOptions& options, RendererScene& scene,
  417. const FrameInfo& frameInfo);
  418. /** Renders shadow maps for the provided radial light. */
  419. void renderRadialShadowMap(const RendererLight& light, const ShadowMapOptions& options, RendererScene& scene,
  420. const FrameInfo& frameInfo);
  421. /**
  422. * Calculates optimal shadow map size, taking into account all views in the scene. Also calculates a fade value
  423. * that can be used for fading out small shadow maps.
  424. *
  425. * @param[in] light Light for which to calculate the shadow map properties. Cannot be a directional light.
  426. * @param[in] viewGroup All the views the shadow will (potentially) be seen through.
  427. * @param[in] border Border to reduce the shadow map size by, in pixels.
  428. * @param[out] size Optimal size of the shadow map, in pixels.
  429. * @param[out] fadePercents Value in range [0, 1] determining how much should the shadow map be faded out. Each
  430. * entry corresponds to a single view.
  431. * @param[out] maxFadePercent Maximum value in the @p fadePercents array.
  432. */
  433. void calcShadowMapProperties(const RendererLight& light, const RendererViewGroup& viewGroup, UINT32 border,
  434. UINT32& size, SmallVector<float, 6>& fadePercents, float& maxFadePercent) const;
  435. /**
  436. * Draws a mesh representing near and far planes at the provided coordinates. The mesh is constructed using
  437. * normalized device coordinates and requires no perspective transform. Near plane will be drawn using front facing
  438. * triangles, and the far plane will be drawn using back facing triangles.
  439. *
  440. * @param[in] near Location of the near plane, in NDC.
  441. * @param[in] far Location of the far plane, in NDC.
  442. * @param[in] drawNear If disabled, only the far plane will be drawn.
  443. */
  444. void drawNearFarPlanes(float near, float far, bool drawNear = true) const;
  445. /**
  446. * Draws a frustum mesh using the provided vertices as its corners. Corners should be in the order specified
  447. * by AABox::Corner enum.
  448. */
  449. void drawFrustum(const std::array<Vector3, 8>& corners) const;
  450. /**
  451. * Calculates optimal shadow quality based on the quality set in the options and the actual shadow map resolution.
  452. */
  453. static UINT32 getShadowQuality(UINT32 requestedQuality, UINT32 shadowMapResolution, UINT32 minAllowedQuality);
  454. /**
  455. * Generates a frustum for a single cascade of a cascaded shadow map. Also outputs spherical bounds of the
  456. * split view frustum.
  457. *
  458. * @param[in] view View whose frustum to split.
  459. * @param[in] lightDir Direction of the light for which we're generating the shadow map.
  460. * @param[in] cascade Index of the cascade to generate the frustum for.
  461. * @param[in] numCascades Maximum number of cascades in the cascaded shadow map. Must be greater than zero.
  462. * @param[out] outBounds Spherical bounds of the split view frustum.
  463. * @return Convex volume covering the area of the split view frustum visible from the light.
  464. */
  465. static ConvexVolume getCSMSplitFrustum(const RendererView& view, const Vector3& lightDir, UINT32 cascade,
  466. UINT32 numCascades, Sphere& outBounds);
  467. /**
  468. * Finds the distance (along the view direction) of the frustum split for the specified index. Used for cascaded
  469. * shadow maps.
  470. *
  471. * @param[in] view View whose frustum to split.
  472. * @param[in] index Index of the split. 0 = near plane.
  473. * @param[in] numCascades Maximum number of cascades in the cascaded shadow map. Must be greater than
  474. * zero and greater or equal to @p index.
  475. * @return Distance to the split position along the view direction.
  476. */
  477. static float getCSMSplitDistance(const RendererView& view, UINT32 index, UINT32 numCascades);
  478. /**
  479. * Calculates a bias that can be applied when rendering shadow maps, in order to reduce shadow artifacts.
  480. *
  481. * @param[in] light Light to calculate the depth bias for.
  482. * @param[in] radius Radius of the light bounds.
  483. * @param[in] depthRange Range of depths (distance between near and far planes) covered by the shadow.
  484. * @param[in] mapSize Size of the shadow map, in pixels.
  485. * @return Depth bias that can be passed to shadow depth rendering shader.
  486. */
  487. static float getDepthBias(const Light& light, float radius, float depthRange, UINT32 mapSize);
  488. /**
  489. * Calculates a fade transition value that can be used for slowly fading-in the shadow, in order to avoid or reduce
  490. * shadow acne.
  491. *
  492. * @param[in] light Light to calculate the fade transition size for.
  493. * @param[in] radius Radius of the light bounds.
  494. * @param[in] depthRange Range of depths (distance between near and far planes) covered by the shadow.
  495. * @param[in] mapSize Size of the shadow map, in pixels.
  496. * @return Value that determines the size of the fade transition region.
  497. */
  498. static float getFadeTransition(const Light& light, float radius, float depthRange, UINT32 mapSize);
  499. /** Size of a single shadow map atlas, in pixels. */
  500. static const UINT32 MAX_ATLAS_SIZE;
  501. /** Determines how long will an unused shadow map atlas stay allocated, in frames. */
  502. static const UINT32 MAX_UNUSED_FRAMES;
  503. /** Determines the minimal resolution of a shadow map. */
  504. static const UINT32 MIN_SHADOW_MAP_SIZE;
  505. /** Determines the resolution at which shadow maps begin fading out. */
  506. static const UINT32 SHADOW_MAP_FADE_SIZE;
  507. /** Size of the border of a shadow map in a shadow map atlas, in pixels. */
  508. static const UINT32 SHADOW_MAP_BORDER;
  509. /** Percent of the length of a single cascade in a CSM, in which to fade out the cascade. */
  510. static const float CASCADE_FRACTION_FADE;
  511. UINT32 mShadowMapSize;
  512. Vector<ShadowMapAtlas> mDynamicShadowMaps;
  513. Vector<ShadowCascadedMap> mCascadedShadowMaps;
  514. Vector<ShadowCubemap> mShadowCubemaps;
  515. Vector<ShadowInfo> mShadowInfos;
  516. Vector<LightShadows> mSpotLightShadows;
  517. Vector<LightShadows> mRadialLightShadows;
  518. Vector<PerViewLightShadows> mDirectionalLightShadows;
  519. SPtr<VertexDeclaration> mPositionOnlyVD;
  520. // Mesh information used for drawing near & far planes
  521. mutable SPtr<IndexBuffer> mPlaneIB;
  522. mutable SPtr<VertexBuffer> mPlaneVB;
  523. // Mesh information used for drawing a shadow frustum
  524. mutable SPtr<IndexBuffer> mFrustumIB;
  525. mutable SPtr<VertexBuffer> mFrustumVB;
  526. Vector<bool> mRenderableVisibility; // Transient
  527. Vector<ShadowMapOptions> mSpotLightShadowOptions; // Transient
  528. Vector<ShadowMapOptions> mRadialLightShadowOptions; // Transient
  529. };
  530. /* @} */
  531. }}