Add Global SDF mip sampling in DDGI probes classification to prevent flickering on large maps
This commit is contained in:
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user