Improve DDGI quality by not using lower-res cascade fallback
This commit is contained in:
@@ -136,43 +136,34 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
||||
{
|
||||
// Select the highest cascade that contains the sample location
|
||||
uint cascadeIndex = 0;
|
||||
float4 probesDatas[8];
|
||||
float probesSpacing = 0;
|
||||
float3 probesOrigin = (float3)0, probesExtent = (float3)0;
|
||||
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
||||
{
|
||||
float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||
float3 probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
||||
float3 probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
||||
probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||
probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
||||
probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
||||
float fadeDistance = probesSpacing * 0.5f;
|
||||
float cascadeWeight = saturate(Min3(probesExtent - abs(worldPosition - probesOrigin)) / fadeDistance);
|
||||
if (cascadeWeight > dither) // Use dither to make transition smoother
|
||||
{
|
||||
// Load probes state for this cascade
|
||||
uint activeCount = 0;
|
||||
uint3 baseProbeCoords = clamp(uint3((worldPosition - probesOrigin + probesExtent) / probesSpacing), uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
UNROLL
|
||||
for (uint i = 0; i < 8; i++)
|
||||
{
|
||||
uint3 probeCoordsOffset = uint3(i, i >> 1, i >> 2) & 1;
|
||||
uint3 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||
float4 probeData = LoadDDGIProbeData(data, probesData, cascadeIndex, probeIndex);
|
||||
probesDatas[i] = probeData;
|
||||
uint probeState = DecodeDDGIProbeState(probeData);
|
||||
if (probeState != DDGI_PROBE_STATE_INACTIVE)
|
||||
activeCount++;
|
||||
}
|
||||
|
||||
// Ensure there are some valid probes in this cascade
|
||||
if (activeCount >= 3)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cascadeIndex == data.CascadesCount)
|
||||
return data.FallbackIrradiance;
|
||||
uint3 baseProbeCoords = clamp(uint3((worldPosition - probesOrigin + probesExtent) / probesSpacing), uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
|
||||
float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||
float3 probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
||||
float3 probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
||||
// Load probes state for this cascade
|
||||
float4 probesDatas[8];
|
||||
UNROLL
|
||||
for (uint i = 0; i < 8; i++)
|
||||
{
|
||||
uint3 probeCoordsOffset = uint3(i, i >> 1, i >> 2) & 1;
|
||||
uint3 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||
probesDatas[i] = LoadDDGIProbeData(data, probesData, cascadeIndex, probeIndex);
|
||||
}
|
||||
|
||||
// Bias the world-space position to reduce artifacts
|
||||
float3 viewDir = normalize(data.ViewPos - worldPosition);
|
||||
@@ -180,7 +171,6 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
||||
float3 biasedWorldPosition = worldPosition + surfaceBias;
|
||||
|
||||
// Get the grid coordinates of the probe nearest the biased world position
|
||||
uint3 baseProbeCoords = clamp(uint3((worldPosition - probesOrigin + probesExtent) / probesSpacing), uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
float3 baseProbeWorldPosition = GetDDGIProbeWorldPosition(data, cascadeIndex, baseProbeCoords);
|
||||
float3 biasAlpha = saturate((biasedWorldPosition - baseProbeWorldPosition) / probesSpacing);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define DDGI_TRACE_RAYS_LIMIT 256 // Limit of rays per-probe (runtime value can be smaller)
|
||||
#define DDGI_PROBE_UPDATE_BORDERS_GROUP_SIZE 8
|
||||
#define DDGI_PROBE_CLASSIFY_GROUP_SIZE 32
|
||||
#define DDGI_PROBE_RELOCATE_ITERATIVE 0 // If true, probes relocation algorithm tries to move them in additive way, otherwise all nearby locations are checked to find the best position
|
||||
|
||||
META_CB_BEGIN(0, Data0)
|
||||
DDGIData DDGI;
|
||||
@@ -67,8 +68,6 @@ uint GetProbeRaysCount(DDGIData data, uint probeState)
|
||||
|
||||
#ifdef _CS_Classify
|
||||
|
||||
#define DDGI_PROBE_RELOCATE_ITERATIVE 0 // If true, probes relocation algorithm tries to move them in additive way, otherwise all nearby locations are checked to find the best position
|
||||
|
||||
RWTexture2D<snorm float4> RWProbesData : register(u0);
|
||||
RWByteAddressBuffer RWActiveProbes : register(u1);
|
||||
|
||||
@@ -93,13 +92,29 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords);
|
||||
int2 probeDataCoords = GetDDGIProbeTexelCoords(DDGI, CascadeIndex, probeIndex);
|
||||
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
||||
float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, CascadeIndex, probeCoords);
|
||||
|
||||
// Disable probes that are is in the range of higher-quality cascade
|
||||
if (CascadeIndex > 0)
|
||||
{
|
||||
uint prevCascade = CascadeIndex - 1;
|
||||
float prevProbesSpacing = DDGI.ProbesOriginAndSpacing[prevCascade].w;
|
||||
float3 prevProbesOrigin = DDGI.ProbesScrollOffsets[prevCascade].xyz * prevProbesSpacing + DDGI.ProbesOriginAndSpacing[prevCascade].xyz;
|
||||
float3 prevProbesExtent = (DDGI.ProbesCounts - 1) * (prevProbesSpacing * 0.5f);
|
||||
float prevCascadeWeight = Min3(prevProbesExtent - abs(probeBasePosition - prevProbesOrigin));
|
||||
if (prevCascadeWeight > 0.1f)
|
||||
{
|
||||
// Disable probe
|
||||
RWProbesData[probeDataCoords] = EncodeDDGIProbeData(float3(0, 0, 0), DDGI_PROBE_STATE_INACTIVE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Load probe state and position
|
||||
float4 probeData = RWProbesData[probeDataCoords];
|
||||
uint probeState = DecodeDDGIProbeState(probeData);
|
||||
float3 probeOffset = probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||
float3 probeOffsetOld = probeOffset;
|
||||
float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, CascadeIndex, probeCoords);
|
||||
float3 probePosition = probeBasePosition;
|
||||
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
||||
probePosition += probeOffset;
|
||||
|
||||
Reference in New Issue
Block a user