Add Global SDF mip sampling in DDGI probes classification to prevent flickering on large maps

This commit is contained in:
2022-06-13 15:28:46 +02:00
parent e96e6bea86
commit 6c45fff205
3 changed files with 43 additions and 2 deletions
@@ -487,6 +487,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
PROFILE_GPU_CPU("Probes Classification");
uint32 threadGroups = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE);
bindingDataSDF.BindCascades(context, 0);
bindingDataSDF.BindCascadeMips(context, 4);
context->BindUA(0, ddgiData.Result.ProbesState);
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
{
+3 -2
View File
@@ -61,6 +61,7 @@ float3 GetProbeRayDirection(DDGIData data, uint rayIndex)
RWTexture2D<float4> RWProbesState : register(u0);
Texture3D<float> GlobalSDFTex[4] : register(t0);
Texture3D<float> GlobalSDFMip[4] : register(t4);
// Compute shader for updating probes state between active and inactive.
META_CS(true, FEATURE_LEVEL_SM5)
@@ -84,10 +85,10 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
// Use Global SDF to quickly get distance and direction to the scene geometry
float sdf;
float3 sdfNormal = normalize(SampleGlobalSDFGradient(GlobalSDF, GlobalSDFTex, probePosition.xyz, sdf));
float3 sdfNormal = normalize(SampleGlobalSDFGradient(GlobalSDF, GlobalSDFTex, GlobalSDFMip, probePosition.xyz, sdf));
float sdfDst = abs(sdf);
float threshold = GlobalSDF.CascadeVoxelSize[CascadeIndex];
float distanceLimit = length(probesSpacing) * 2.0f;
float distanceLimit = length(probesSpacing) * 1.5f;
float relocateLimit = length(probesSpacing) * 0.6f;
if (sdfDst > distanceLimit) // Probe is too far from geometry
{
@@ -114,6 +114,45 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4]
return gradient;
}
// Samples the Global SDF and returns the gradient vector (derivative) at the given world location. Normalize it to get normal vector.
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4], Texture3D<float> mips[4], float3 worldPosition, out float distance)
{
float3 gradient = float3(0, 0.00001f, 0);
distance = GLOBAL_SDF_WORLD_SIZE;
if (data.CascadePosDistance[3].w <= 0.0f)
return gradient;
float chunkSizeDistance = (float)GLOBAL_SDF_RASTERIZE_CHUNK_SIZE / data.Resolution; // Size of the chunk in SDF distance (0-1)
float chunkMarginDistance = (float)GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN / data.Resolution; // Size of the chunk margin in SDF distance (0-1)
UNROLL
for (uint cascade = 0; cascade < data.CascadesCount; cascade++)
{
float4 cascadePosDistance = data.CascadePosDistance[cascade];
float cascadeMaxDistance = cascadePosDistance.w * 2;
float3 posInCascade = worldPosition - cascadePosDistance.xyz;
float3 cascadeUV = posInCascade / cascadeMaxDistance + 0.5f;
float cascadeDistance = mips[cascade].SampleLevel(SamplerLinearClamp, cascadeUV, 0);
if (cascadeDistance < chunkSizeDistance && !any(cascadeUV < 0) && !any(cascadeUV > 1))
{
float cascadeDistanceTex = tex[cascade].SampleLevel(SamplerLinearClamp, cascadeUV, 0);
if (cascadeDistanceTex < chunkMarginDistance * 2)
{
cascadeDistance = cascadeDistanceTex;
}
float texelOffset = 1.0f / data.Resolution;
float xp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x + texelOffset, cascadeUV.y, cascadeUV.z), 0).x;
float xn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x - texelOffset, cascadeUV.y, cascadeUV.z), 0).x;
float yp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y + texelOffset, cascadeUV.z), 0).x;
float yn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y - texelOffset, cascadeUV.z), 0).x;
float zp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y, cascadeUV.z + texelOffset), 0).x;
float zn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y, cascadeUV.z - texelOffset), 0).x;
gradient = float3(xp - xn, yp - yn, zp - zn) * cascadeMaxDistance;
distance = cascadeDistance * cascadeMaxDistance;
break;
}
}
return gradient;
}
// Ray traces the Global SDF.
GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], Texture3D<float> mips[4], const GlobalSDFTrace trace)
{