Improve DDGI probes relocation algorithm

This commit is contained in:
Wojciech Figat
2022-06-03 17:43:12 +02:00
parent befaf65ab1
commit 79220556df
3 changed files with 35 additions and 25 deletions

BIN
Content/Shaders/GI/DDGI.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -143,16 +143,17 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<float4> probesState, Textur
float4 probeState = probesState.Load(int3(GetDDGIProbeTexelCoords(data, probeIndex), 0));
if (probeState.w == DDGI_PROBE_STATE_INACTIVE)
continue;
float3 probePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * data.ProbesSpacing) + probeState.xyz;
float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * data.ProbesSpacing);
float3 probePosition = probeBasePosition + probeState.xyz;
// Calculate the distance and direction from the (biased and non-biased) shading point and the probe
float3 worldPosToProbe = normalize(probePosition.xyz - worldPosition);
float3 biasedPosToProbe = normalize(probePosition.xyz - biasedWorldPosition);
float biasedPosToProbeDist = length(probePosition.xyz - biasedWorldPosition);
float3 worldPosToProbe = normalize(probePosition - worldPosition);
float3 biasedPosToProbe = normalize(probePosition - biasedWorldPosition);
float biasedPosToProbeDist = length(probePosition - biasedWorldPosition);
// Smooth backface test
float weight = Square(dot(worldPosToProbe, worldNormal) * 0.5f + 0.5f);
// Sample distance texture
float2 octahedralCoords = GetOctahedralCoords(-biasedPosToProbe);
float2 uv = GetDDGIProbeUV(data, probeIndex, octahedralCoords, DDGI_PROBE_RESOLUTION_DISTANCE);

View File

@@ -71,44 +71,53 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
// Load probe state and position
float4 probeState = RWProbesState[probeDataCoords];
float3 probePosition = GetDDGIProbeWorldPosition(DDGI, probeCoords);
// TODO: reset probe offset for scrolled probes
probePosition.xyz += probeState.xyz;
float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, probeCoords);
float3 probePosition = probeBasePosition + probeState.xyz;
probeState.w = DDGI_PROBE_STATE_ACTIVE;
// Use Global SDF to quickly get distance and direction to the scene geometry
float sdf;
float3 sdfNormal = normalize(SampleGlobalSDFGradient(GlobalSDF, GlobalSDFTex, probePosition.xyz, sdf));
float threshold = GlobalSDF.CascadeVoxelSize[0] * 0.5f;
float distanceLimit = length(DDGI.ProbesSpacing) * 1.5f + threshold;
float distanceLimit = length(DDGI.ProbesSpacing) * 2.0f;
float relocateLimit = length(DDGI.ProbesSpacing) * 0.6f;
if (abs(sdf) > distanceLimit + threshold) // Probe is too far from geometry
if (abs(sdf) > distanceLimit) // Probe is too far from geometry
{
// Disable it
probeState = float4(0, 0, 0, DDGI_PROBE_STATE_INACTIVE);
}
else if (sdf < threshold) // Probe is inside geometry
else
{
if (abs(sdf) < relocateLimit)
if (sdf < threshold) // Probe is inside geometry
{
float3 offsetToAdd = sdfNormal * (sdf + threshold);
if (distance(probeState.xyz, offsetToAdd) < relocateLimit)
if (abs(sdf) < relocateLimit)
{
// Relocate it
probeState.xyz = probeState.xyz + offsetToAdd;
float3 offsetToAdd = sdfNormal * sdf;
if (distance(probeState.xyz, offsetToAdd) < relocateLimit)
{
// Relocate it
probeState.xyz += offsetToAdd;
}
}
else
{
// Reset relocation
probeState.xyz = float3(0, 0, 0);
}
// TODO: maybe sample SDF at the relocated location and disable probe if it's still in the geometry?
}
else
else if (sdf > threshold * 2.0f) // Probe is far enough any geometry
{
// Reset relocation
probeState.xyz = float3(0, 0, 0);
}
// Check if probe is relocated but the base location is fine
sdf = SampleGlobalSDF(GlobalSDF, GlobalSDFTex, probeBasePosition.xyz);
if (sdf > threshold)
{
// Reset relocation
probeState.xyz = float3(0, 0, 0);
}
}
else if (sdf > relocateLimit) // Probe is far enough any geometry
{
// Reset relocation
probeState.xyz = float3(0, 0, 0);
}
RWProbesState[probeDataCoords] = probeState;