diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 010f8f001..0614dd00b 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -146,7 +146,6 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, _cache.GridPixelSize = 16; _cache.GridSizeZ = 64; _cache.FogJitter = false; - _cache.TemporalReprojection = false; _cache.MissedHistorySamplesCount = 1; break; } @@ -155,7 +154,6 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, _cache.GridPixelSize = 16; _cache.GridSizeZ = 64; _cache.FogJitter = true; - _cache.TemporalReprojection = true; _cache.MissedHistorySamplesCount = 4; break; } @@ -164,7 +162,6 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, _cache.GridPixelSize = 16; _cache.GridSizeZ = 128; _cache.FogJitter = true; - _cache.TemporalReprojection = true; _cache.MissedHistorySamplesCount = 4; break; } @@ -173,7 +170,6 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, _cache.GridPixelSize = 8; _cache.GridSizeZ = 256; _cache.FogJitter = true; - _cache.TemporalReprojection = true; _cache.MissedHistorySamplesCount = 8; break; } @@ -214,7 +210,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, { _cache.Data.FrameJitterOffsets[i] = defaultOffset; } - if (_cache.FogJitter && _cache.TemporalReprojection) + if (_cache.FogJitter) { for (int32 i = 0; i < _cache.MissedHistorySamplesCount; i++) { @@ -320,7 +316,7 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte InitCircleBuffer(); // Call rendering to the volume - const int32 psIndex = (_cache.TemporalReprojection ? 1 : 0) + 2; + const int32 psIndex = 1; context->SetState(_psInjectLight.Get(psIndex)); const int32 instanceCount = volumeZBoundsMax - volumeZBoundsMin; const int32 indexCount = _ibCircleRasterize->GetElementsCount(); @@ -379,7 +375,7 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte InitCircleBuffer(); // Call rendering to the volume - const int32 psIndex = (cache.TemporalReprojection ? 1 : 0) + (withShadow ? 2 : 0); + const int32 psIndex = withShadow ? 1 : 0; context->SetState(_psInjectLight.Get(psIndex)); const int32 instanceCount = volumeZBoundsMax - volumeZBoundsMin; const int32 indexCount = _ibCircleRasterize->GetElementsCount(); @@ -479,12 +475,6 @@ void VolumetricFogPass::Render(RenderContext& renderContext) context->UpdateCB(cb0, &_cache.Data); context->BindCB(0, cb0); - // Peek flags - const bool temporalHistoryIsValid = cache.TemporalReprojection - && renderContext.Buffers->VolumetricFogHistory - && !renderContext.Task->IsCameraCut - && Float3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize); - // Allocate buffers const GPUTextureDescription volumeDesc = GPUTextureDescription::New3D(cache.GridSize, PixelFormat::R16G16B16A16_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess); const GPUTextureDescription volumeDescRGB = GPUTextureDescription::New3D(cache.GridSize, PixelFormat::R11G11B10_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess); @@ -646,6 +636,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) { PROFILE_GPU("Light Scattering"); + const bool temporalHistoryIsValid = renderContext.Buffers->VolumetricFogHistory && !renderContext.Task->IsCameraCut && Float3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize); const auto lightScatteringHistory = temporalHistoryIsValid ? renderContext.Buffers->VolumetricFogHistory : nullptr; context->BindUA(0, lightScattering->ViewVolume()); @@ -656,7 +647,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) context->BindSR(4, dirLightShadowMap); context->BindSR(5, skyLightImage); - const int32 csIndex = cache.TemporalReprojection ? 1 : 0; + const int32 csIndex = 0; context->Dispatch(_csLightScattering.Get(csIndex), groupCountX, groupCountY, groupCountZ); context->ResetSR(); diff --git a/Source/Engine/Renderer/VolumetricFogPass.h b/Source/Engine/Renderer/VolumetricFogPass.h index e5bc087aa..d874c039c 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.h +++ b/Source/Engine/Renderer/VolumetricFogPass.h @@ -81,9 +81,9 @@ private: // Shader stuff AssetReference _shader; GPUShaderProgramCS* _csInitialize = nullptr; - ComputeShaderPermutation<2> _csLightScattering; + ComputeShaderPermutation<1> _csLightScattering; GPUShaderProgramCS* _csFinalIntegration = nullptr; - GPUPipelineStatePermutationsPs<4> _psInjectLight; + GPUPipelineStatePermutationsPs<2> _psInjectLight; GPUBuffer* _vbCircleRasterize = nullptr; GPUBuffer* _ibCircleRasterize = nullptr; @@ -108,11 +108,6 @@ private: /// bool FogJitter; - /// - /// Whether to use temporal reprojection on volumetric fog. - /// - bool TemporalReprojection; - /// /// How much the history value should be weighted each frame. This is a tradeoff between visible jittering and responsiveness. /// diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index d595049ff..68266b11e 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -185,10 +185,8 @@ float ComputeVolumeShadowing(float3 worldPosition, bool isSpotLight) #endif META_PS(true, FEATURE_LEVEL_SM5) -META_PERMUTATION_2(USE_TEMPORAL_REPROJECTION=0, USE_SHADOW=0) -META_PERMUTATION_2(USE_TEMPORAL_REPROJECTION=1, USE_SHADOW=0) -META_PERMUTATION_2(USE_TEMPORAL_REPROJECTION=0, USE_SHADOW=1) -META_PERMUTATION_2(USE_TEMPORAL_REPROJECTION=1, USE_SHADOW=1) +META_PERMUTATION_1(USE_SHADOW=0) +META_PERMUTATION_1(USE_SHADOW=1) float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 { uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex); @@ -197,18 +195,12 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 if (!all(gridCoordinate < GridSizeInt)) return 0; -#if USE_TEMPORAL_REPROJECTION float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip); float historyAlpha = HistoryWeight; FLATTEN if (any(historyUV < 0) || any(historyUV > 1)) - { historyAlpha = 0; - } uint samplesCount = historyAlpha < 0.001f ? MissedHistorySamplesCount : 1; -#else - uint samplesCount = 1; -#endif float NoL = 0; float distanceAttenuation = 1; @@ -298,28 +290,19 @@ TextureCube SkyLightImage : register(t5); #define THREADGROUP_SIZE 4 META_CS(true, FEATURE_LEVEL_SM5) -META_PERMUTATION_1(USE_TEMPORAL_REPROJECTION=0) -META_PERMUTATION_1(USE_TEMPORAL_REPROJECTION=1) [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)] void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint3 GroupThreadId : SV_GroupThreadID) { uint3 gridCoordinate = DispatchThreadId; float3 lightScattering = 0; uint samplesCount = 1; - -#if USE_TEMPORAL_REPROJECTION + float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip); float historyAlpha = HistoryWeight; - - // Discard history if it lays outside the current view FLATTEN if (any(historyUV < 0) || any(historyUV > 1)) - { historyAlpha = 0; - } - samplesCount = historyAlpha < 0.001f && all(gridCoordinate < GridSizeInt) ? MissedHistorySamplesCount : 1; -#endif for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) { @@ -363,15 +346,13 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ float extinction = materialScatteringAndAbsorption.w + Luminance(materialScatteringAndAbsorption.xyz); float3 materialEmissive = VBufferB[gridCoordinate].xyz; float4 scatteringAndExtinction = float4(lightScattering * materialScatteringAndAbsorption.xyz + materialEmissive, extinction); - -#if USE_TEMPORAL_REPROJECTION + BRANCH if (historyAlpha > 0) { float4 historyScatteringAndExtinction = LightScatteringHistory.SampleLevel(SamplerLinearClamp, historyUV, 0); scatteringAndExtinction = lerp(scatteringAndExtinction, historyScatteringAndExtinction, historyAlpha); } -#endif if (all(gridCoordinate < GridSizeInt)) {