diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index edffa9f4a..7d1177797 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -103,8 +103,12 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) float4 probeStateOld = probeState; // Use Global SDF to quickly get distance and direction to the scene geometry +#if DDGI_PROBE_RELOCATE_ITERATIVE float sdf; float3 sdfNormal = normalize(SampleGlobalSDFGradient(GlobalSDF, GlobalSDFTex, GlobalSDFMip, probePosition, sdf)); +#else + float sdf = SampleGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, probePosition); +#endif float sdfDst = abs(sdf); float threshold = GlobalSDF.CascadeVoxelSize[CascadeIndex]; float distanceLimit = length(probesSpacing) * 1.5f; diff --git a/Source/Shaders/GlobalSignDistanceField.hlsl b/Source/Shaders/GlobalSignDistanceField.hlsl index 34c64577d..db6fab98a 100644 --- a/Source/Shaders/GlobalSignDistanceField.hlsl +++ b/Source/Shaders/GlobalSignDistanceField.hlsl @@ -107,7 +107,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex, float3 wor float3 cascadeUV, textureUV; GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); - if (cascadeDistance < 1.0f && !any(cascadeUV < 0) && !any(cascadeUV > 1)) + if (cascadeDistance < 0.9f && !any(cascadeUV < 0) && !any(cascadeUV > 1)) { distance = cascadeDistance * cascadeMaxDistance; break; @@ -116,6 +116,32 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex, float3 wor return distance; } +// Samples the Global SDF and returns the distance to the closest surface (in world units) at the given world location. +float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex, Texture3D mip, float3 worldPosition) +{ + float distance = data.CascadePosDistance[3].w * 2.0f; + if (distance <= 0.0f) + return GLOBAL_SDF_WORLD_SIZE; + 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) + for (uint cascade = 0; cascade < data.CascadesCount; cascade++) + { + float cascadeMaxDistance; + float3 cascadeUV, textureUV; + GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); + float cascadeDistance = mip.SampleLevel(SamplerLinearClamp, textureUV, 0); + if (cascadeDistance < chunkSizeDistance && !any(cascadeUV < 0) && !any(cascadeUV > 1)) + { + float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); + if (cascadeDistanceTex < chunkMarginDistance * 2) + cascadeDistance = cascadeDistanceTex; + distance = cascadeDistance * cascadeMaxDistance; + break; + } + } + return distance; +} + // 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 tex, float3 worldPosition, out float distance) { @@ -165,9 +191,7 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D tex, T { float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); if (cascadeDistanceTex < chunkMarginDistance * 2) - { cascadeDistance = cascadeDistanceTex; - } float texelOffset = 1.0f / data.Resolution; float xp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x; float xn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x - texelOffset, textureUV.y, textureUV.z), 0).x;