From 846be3c329256dc29ccb7970973b3584fbe8e147 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Jul 2026 23:10:50 +0200 Subject: [PATCH] Add noise to DDGI specular to hide low-res probes pixelization --- Source/Shaders/GI/DDGI.hlsl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index a6723e915..df42e0586 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -349,6 +349,14 @@ float3 SampleDDGIIrradianceCascade(DDGIData data, Texture2D probes return totalIrradiance.rgb; } +// Cheap, deterministic 3D hash function in range [-1; 1] +float3 DDGIHash3D(float3 p) +{ + p = frac(p * float3(443.8975, 397.2973, 491.1871)); + p += dot(p.xyz, p.yzx + 19.19); + return frac(frac(p.xxy * p.yzz) * 2.0 - 1.0); +} + float3 SampleDDGISpecularCascade(DDGIData data, Texture2D probesData, Texture2D probesDistance, Texture2D probesRadiance, float3 worldPosition, float3 worldNormal, float3 reflection, DDGICascadeSampling cascade) { bool invalidCascade = cascade.CascadeIndex >= data.CascadesCount; @@ -365,6 +373,7 @@ float3 SampleDDGISpecularCascade(DDGIData data, Texture2D probesDa #endif DDGIProbeBase base = GetDDGIProbeBase(data, cascade, worldPosition); + float3 worldNoise = DDGIHash3D(worldPosition) * 0.1f; // Loop over the closest probes to accumulate their contributions float4 totalRadiance = float4(0, 0, 0, 0); @@ -377,6 +386,9 @@ float3 SampleDDGISpecularCascade(DDGIData data, Texture2D probesDa //float3 sampleVector = normalize((worldPosition - probe.ProbePosition) / (cascade.ProbesSpacing * 2) + reflection); float3 sampleVector = reflection; + // Randomize sample vector to reduce blocky artifacts (due to low-res of probe) + sampleVector += worldNoise; + // Sample radiance texture float2 octahedralCoords = GetOctahedralCoords(sampleVector); float2 uv = GetDDGIProbeUV(data, cascade.CascadeIndex, probe.ProbeIndex, octahedralCoords, DDGI_PROBE_RESOLUTION_RADIANCE);