// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Graphics/RenderView.h" #include "Engine/Graphics/GPUPipelineStatePermutations.h" #include "RendererPass.h" #include "GI/DynamicDiffuseGlobalIllumination.h" struct VolumetricFogOptions; struct RendererSpotLightData; struct RendererPointLightData; /// /// Volumetric fog rendering service. /// class VolumetricFogPass : public RendererPass { public: struct CustomData { GPUShader* Shader; Float3 GridSize; float VolumetricFogMaxDistance; int32 ParticleIndex; }; private: PACK_STRUCT(struct SkyLightData { Float3 MultiplyColor; float VolumetricScatteringIntensity; Float3 AdditiveColor; float Dummt0; }); PACK_STRUCT(struct Data { GBufferData GBuffer; Float3 GlobalAlbedo; float GlobalExtinctionScale; Float3 GlobalEmissive; float HistoryWeight; Float3 GridSize; uint32 MissedHistorySamplesCount; uint32 GridSizeIntX; uint32 GridSizeIntY; uint32 GridSizeIntZ; float PhaseG; Float2 Dummy0; float VolumetricFogMaxDistance; float InverseSquaredLightDistanceBiasScale; Float4 FogParameters; Matrix PrevWorldToClip; Float4 FrameJitterOffsets[8]; LightData DirectionalLight; LightShadowData DirectionalLightShadow; SkyLightData SkyLight; DynamicDiffuseGlobalIlluminationPass::ConstantsData DDGI; }); PACK_STRUCT(struct PerLight { Float2 SliceToDepth; int32 MinZ; float LocalLightScatteringIntensity; Float4 ViewSpaceBoundingSphere; Matrix ViewToVolumeClip; LightData LocalLight; LightShadowData LocalLightShadow; }); // Shader stuff AssetReference _shader; GPUShaderProgramCS* _csInitialize = nullptr; ComputeShaderPermutation<2> _csLightScattering; GPUShaderProgramCS* _csFinalIntegration = nullptr; GPUPipelineStatePermutationsPs<2> _psInjectLight; GPUBuffer* _vbCircleRasterize = nullptr; GPUBuffer* _ibCircleRasterize = nullptr; /// /// The current frame cache (initialized during Init) /// struct FrameCache { /// /// The XY size of a cell in the voxel grid, in pixels. /// int32 GridPixelSize; /// /// How many Volumetric Fog cells to use in z (depth from camera). /// int32 GridSizeZ; /// /// Whether to apply jitter to each frame's volumetric fog. Should be used with temporal reprojection to improve the quality. /// bool FogJitter; /// /// How much the history value should be weighted each frame. This is a tradeoff between visible jittering and responsiveness. /// float HistoryWeight; /// /// The amount of lighting samples to compute for voxels whose history value is not available. This reduces noise when panning or on camera cuts, but introduces a variable cost to volumetric fog computation. Valid range [1, 8]. /// int32 MissedHistorySamplesCount; /// /// Scales the amount added to the inverse squared falloff denominator. This effectively removes the spike from inverse squared falloff that causes extreme aliasing. /// float InverseSquaredLightDistanceBiasScale; /// /// The calculated size of the volume texture. /// Float3 GridSize; /// /// The cached per-frame data for the constant buffer. /// Data Data; }; FrameCache _cache; bool _isSupported; public: /// /// Init /// VolumetricFogPass(); public: /// /// Renders the light to the volumetric fog light scattering volume texture. Called by the light pass after shadow map rendering. Used by the shadows casting lights. /// /// The rendering context. /// The GPU commands context. /// The light. /// The shadow map. /// The light shadow data. void RenderLight(RenderContext& renderContext, GPUContext* context, RendererPointLightData& light, GPUTextureView* shadowMap, LightShadowData& shadow); /// /// Renders the light to the volumetric fog light scattering volume texture. Called by the light pass after shadow map rendering. Used by the shadows casting lights. /// /// The rendering context. /// The GPU commands context. /// The light. /// The shadow map. /// The light shadow data. void RenderLight(RenderContext& renderContext, GPUContext* context, RendererSpotLightData& light, GPUTextureView* shadowMap, LightShadowData& shadow); /// /// Renders the volumetric fog (generates integrated light scattering 3D texture). Does nothing if feature is disabled or not supported. /// /// The rendering context. void Render(RenderContext& renderContext); private: bool Init(RenderContext& renderContext, GPUContext* context, VolumetricFogOptions& options); GPUTextureView* GetLocalShadowedLightScattering(RenderContext& renderContext, GPUContext* context, VolumetricFogOptions& options) const; void InitCircleBuffer(); template void RenderRadialLight(RenderContext& renderContext, GPUContext* context, T& light, LightShadowData& shadow); template void RenderRadialLight(RenderContext& renderContext, GPUContext* context, RenderView& view, VolumetricFogOptions& options, T& light, PerLight& perLight, GPUConstantBuffer* cb1); #if COMPILE_WITH_DEV_ENV void OnShaderReloading(Asset* obj) { _psInjectLight.Release(); _csInitialize = nullptr; _csLightScattering.Clear(); _csFinalIntegration = nullptr; invalidateResources(); } #endif public: // [RendererPass] String ToString() const override; bool Init() override; void Dispose() override; protected: // [RendererPass] bool setupResources() override; };