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