// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Graphics/GPUPipelineStatePermutations.h" #include "RenderList.h" #include "RendererPass.h" #include "Engine/Content/Assets/Shader.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Graphics/RenderTask.h" /// /// Pixel format for fullscreen render target used for shadows calculations /// #define SHADOWS_PASS_SS_RR_FORMAT PixelFormat::R11G11B10_Float template bool CanRenderShadow(const RenderView& view, const T& light) { bool result = false; switch ((ShadowsCastingMode)light.ShadowsMode) { case ShadowsCastingMode::StaticOnly: result = view.IsOfflinePass; break; case ShadowsCastingMode::DynamicOnly: result = !view.IsOfflinePass; break; case ShadowsCastingMode::All: result = true; break; default: break; } return result && light.ShadowsStrength > ZeroTolerance; } /// /// Shadows rendering service. /// class ShadowsPass : public RendererPass { private: struct ShadowData { int32 ContextIndex; int32 ContextCount; bool BlendCSM; LightShadowData Constants; }; // Shader stuff AssetReference _shader; GPUPipelineStatePermutationsPs(Quality::MAX) * 2 * 2> _psShadowDir; GPUPipelineStatePermutationsPs(Quality::MAX) * 2> _psShadowPoint; GPUPipelineStatePermutationsPs(Quality::MAX) * 2> _psShadowSpot; bool _supportsShadows; // Shadow maps stuff int32 _shadowMapsSizeCSM; int32 _shadowMapsSizeCube; GPUTexture* _shadowMapCSM; GPUTexture* _shadowMapCube; Quality _currentShadowMapsQuality; // Shadow map rendering stuff AssetReference _sphereModel; Array _shadowData; // Cached state for the current frame rendering (setup via Prepare) int32 maxShadowsQuality; public: /// /// Init /// ShadowsPass(); public: /// /// Gets current GPU memory usage by the shadow maps /// /// GPU memory used in bytes uint64 GetShadowMapsMemoryUsage() const; public: // TODO: use full scene shadow map atlas with dynamic slots allocation int32 LastDirLightIndex = -1; GPUTextureView* LastDirLightShadowMap = nullptr; LightShadowData LastDirLight; public: /// /// Setups the shadows rendering for batched scene drawing. Checks which lights will cast a shadow. /// void SetupShadows(RenderContext& renderContext, RenderContextBatch& renderContextBatch); /// /// Determines whether can render shadow for the specified light. /// /// The rendering context. /// The light. /// true if can render shadow for the specified light; otherwise, false. bool CanRenderShadow(const RenderContext& renderContext, const RendererPointLightData& light); /// /// Determines whether can render shadow for the specified light. /// /// The rendering context. /// The light. /// true if can render shadow for the specified light; otherwise, false. bool CanRenderShadow(const RenderContext& renderContext, const RendererSpotLightData& light); /// /// Determines whether can render shadow for the specified light. /// /// The rendering context. /// The light. /// true if can render shadow for the specified light; otherwise, false. bool CanRenderShadow(const RenderContext& renderContext, const RendererDirectionalLightData& light); /// /// Renders the shadow mask for the given light. /// /// The rendering context batch. /// The light. /// The shadow mask (output). void RenderShadow(RenderContextBatch& renderContextBatch, RendererPointLightData& light, GPUTextureView* shadowMask); /// /// Renders the shadow mask for the given light. /// /// The rendering context batch. /// The light. /// The shadow mask (output). void RenderShadow(RenderContextBatch& renderContextBatch, RendererSpotLightData& light, GPUTextureView* shadowMask); /// /// Renders the shadow mask for the given light. /// /// The rendering context batch. /// The light. /// The light index. /// The shadow mask (output). void RenderShadow(RenderContextBatch& renderContextBatch, RendererDirectionalLightData& light, int32 index, GPUTextureView* shadowMask); private: void updateShadowMapSize(); void SetupRenderContext(RenderContext& renderContext, RenderContext& shadowContext); void SetupLight(RenderContext& renderContext, RenderContextBatch& renderContextBatch, RendererDirectionalLightData& light); void SetupLight(RenderContext& renderContext, RenderContextBatch& renderContextBatch, RendererPointLightData& light); void SetupLight(RenderContext& renderContext, RenderContextBatch& renderContextBatch, RendererSpotLightData& light); #if COMPILE_WITH_DEV_ENV void OnShaderReloading(Asset* obj) { _psShadowDir.Release(); _psShadowPoint.Release(); _psShadowSpot.Release(); invalidateResources(); } #endif public: // [RendererPass] String ToString() const override; bool Init() override; void Dispose() override; protected: // [RendererPass] bool setupResources() override; };