Fix DDGI probes scrolling to properly handle bigger scroll deltas

This commit is contained in:
Wojtek Figat
2024-06-13 17:04:29 +02:00
parent 5c5fad6bb4
commit 2f688892ea
3 changed files with 42 additions and 28 deletions

View File

@@ -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;
}
}
}

View File

@@ -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)

View File

@@ -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;