From 2f688892ea7c7b368523b3288e5dd5a31d043140 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 13 Jun 2024 17:04:29 +0200 Subject: [PATCH] Fix DDGI probes scrolling to properly handle bigger scroll deltas --- .../GI/DynamicDiffuseGlobalIllumination.cpp | 32 +++++++++++-------- Source/Shaders/GI/DDGI.hlsl | 6 ++-- Source/Shaders/GI/DDGI.shader | 32 +++++++++++-------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index 27bc6a33b..238418a47 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -67,14 +67,12 @@ public: Float3 ProbesOrigin; float ProbesSpacing = 0.0f; Int3 ProbeScrollOffsets; - Int3 ProbeScrollDirections; Int3 ProbeScrollClears; void Clear() { ProbesOrigin = Float3::Zero; ProbeScrollOffsets = Int3::Zero; - ProbeScrollDirections = Int3::Zero; ProbeScrollClears = Int3::Zero; } } Cascades[4]; @@ -400,6 +398,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont const uint64 cascadeFrequencies[] = { 2, 3, 5, 7 }; //const uint64 cascadeFrequencies[] = { 1, 2, 3, 5 }; //const uint64 cascadeFrequencies[] = { 1, 1, 1, 1 }; + //const uint64 cascadeFrequencies[] = { 10, 10, 10, 10 }; bool cascadeSkipUpdate[4]; for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++) { @@ -413,16 +412,6 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont continue; auto& cascade = ddgiData.Cascades[cascadeIndex]; - // Reset the volume origin and scroll offsets for each axis once it overflows - for (int32 axis = 0; axis < 3; axis++) - { - if (cascade.ProbeScrollOffsets.Raw[axis] != 0 && (cascade.ProbeScrollOffsets.Raw[axis] % ddgiData.ProbeCounts.Raw[axis] == 0)) - { - cascade.ProbesOrigin.Raw[axis] += (float)ddgiData.ProbeCounts.Raw[axis] * cascade.ProbesSpacing * (float)cascade.ProbeScrollDirections.Raw[axis]; - cascade.ProbeScrollOffsets.Raw[axis] = 0; - } - } - // Calculate the count of grid cells between the view origin and the scroll anchor const Float3 volumeOrigin = cascade.ProbesOrigin + Float3(cascade.ProbeScrollOffsets) * cascade.ProbesSpacing; const Float3 translation = viewOrigins[cascadeIndex] - volumeOrigin; @@ -432,7 +421,24 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont const int32 scroll = value >= 0.0f ? (int32)Math::Floor(value) : (int32)Math::Ceil(value); cascade.ProbeScrollOffsets.Raw[axis] += scroll; cascade.ProbeScrollClears.Raw[axis] = scroll; - cascade.ProbeScrollDirections.Raw[axis] = translation.Raw[axis] >= 0.0f ? 1 : -1; + } + + // Shift the volume origin based on scroll offsets for each axis once it overflows + for (int32 axis = 0; axis < 3; axis++) + { + // different volume scroll that preserves the scroll offset delta relative to the probe count + const int32 probeCount = ddgiData.ProbeCounts.Raw[axis]; + int32& scrollOffset = cascade.ProbeScrollOffsets.Raw[axis]; + while (scrollOffset >= probeCount) + { + cascade.ProbesOrigin.Raw[axis] += cascade.ProbesSpacing * probeCount; + scrollOffset -= probeCount; + } + while (scrollOffset <= -probeCount) + { + cascade.ProbesOrigin.Raw[axis] -= cascade.ProbesSpacing * probeCount; + scrollOffset += probeCount; + } } } diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index 19619113d..16e79df68 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -77,7 +77,8 @@ uint2 GetDDGIProbeTexelCoords(DDGIData data, uint cascadeIndex, uint probeIndex) uint GetDDGIScrollingProbeIndex(DDGIData data, uint cascadeIndex, uint3 probeCoords) { // Probes are scrolled on edges to stabilize GI when camera moves - return GetDDGIProbeIndex(data, (probeCoords + data.ProbesCounts + data.ProbesScrollOffsets[cascadeIndex].xyz) % data.ProbesCounts); + int3 probeCoordsOffset = (int3)data.ProbesCounts + data.ProbesScrollOffsets[cascadeIndex].xyz; + return GetDDGIProbeIndex(data, (probeCoords + (uint3)probeCoordsOffset) % data.ProbesCounts); } float3 GetDDGIProbeWorldPosition(DDGIData data, uint cascadeIndex, uint3 probeCoords) @@ -86,7 +87,8 @@ float3 GetDDGIProbeWorldPosition(DDGIData data, uint cascadeIndex, uint3 probeCo float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w; float3 probePosition = probeCoords * probesSpacing; float3 probeGridOffset = (probesSpacing * (data.ProbesCounts - 1)) * 0.5f; - return probesOrigin + probePosition - probeGridOffset + (data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing); + float3 probeScrollOffset = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing; + return probesOrigin + probePosition - probeGridOffset + probeScrollOffset; } // Loads probe probe data (encoded) diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index 420333bd3..e9ee51687 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -111,11 +111,28 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) } } + // Check if probe was scrolled + int3 probeScrollClears = ProbeScrollClears[CascadeIndex].xyz; + bool wasScrolled = false; + UNROLL + for (uint planeIndex = 0; planeIndex < 3; planeIndex++) + { + int probeCount = (int)DDGI.ProbesCounts[planeIndex]; + int newCoord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex]; + if (newCoord < 0 || newCoord >= probeCount) + wasScrolled = true; + newCoord = (int)probeCoords[planeIndex] - probeScrollClears[planeIndex]; + if (newCoord < 0 || newCoord >= probeCount) + wasScrolled = true; + } + // Load probe state and position float4 probeData = RWProbesData[probeDataCoords]; uint probeState = DecodeDDGIProbeState(probeData); uint probeStateOld = probeState; float3 probeOffset = probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing + if (wasScrolled || probeState == DDGI_PROBE_STATE_INACTIVE) + probeOffset = float3(0, 0, 0); // Clear offset for a new probe float3 probeOffsetOld = probeOffset; float3 probePosition = probeBasePosition + probeOffset; @@ -207,18 +224,6 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) } } - // Check if probe was scrolled - int3 probeScrollClears = ProbeScrollClears[CascadeIndex].xyz; - bool wasScrolled = false; - UNROLL - for (uint planeIndex = 0; planeIndex < 3; planeIndex++) - { - int probeCount = (int)DDGI.ProbesCounts[planeIndex]; - int newCord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex]; - if (newCord < 0 || newCord >= probeCount) - wasScrolled = true; - } - // If probe was in a different location or was activated now then mark it as activated bool wasActivated = probeStateOld == DDGI_PROBE_STATE_INACTIVE; bool wasRelocated = distance(probeOffset, probeOffsetOld) > 2.0f; @@ -468,8 +473,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ // Blend current value with the previous probe data float historyWeight = DDGI.ProbeHistoryWeight; + //historyWeight = 1.0f; //historyWeight = 0.0f; - if (ResetBlend || wasActivated || dot(previous, previous) == 0) + if (ResetBlend || wasActivated) historyWeight = 0.0f; #if DDGI_PROBE_UPDATE_MODE == 0 result *= DDGI.IndirectLightingIntensity;