Fix DDGI probes scrolling to properly handle bigger scroll deltas
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user