From 0b42d463db23d2c6eb0b6651486912ffed2f8857 Mon Sep 17 00:00:00 2001 From: yum Date: Mon, 16 Mar 2026 16:22:45 -0700 Subject: Fix normal filtering, which fixes both IBL and direct lighting flashing --- pbr.cginc | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'pbr.cginc') diff --git a/pbr.cginc b/pbr.cginc index f3c46a5..33264ce 100755 --- a/pbr.cginc +++ b/pbr.cginc @@ -94,31 +94,28 @@ float2 parallax_offset(float2 uv, float3 view_dir_world, float3x3 tbn) { } #endif // _PARALLAX_HEIGHTMAP -// Tokuyashi and Kaplanyan 2019 "Improved Geometric Specular Antialiasing" -float normalFiltering(float3 normal, float perceptual_roughness) { - float3 du = ddx(normal); - float3 dv = ddy(normal); +// Tokuyoshi and Kaplanyan 2019 "Improved Geometric Specular Antialiasing" +float normalFiltering(float3 geometric_normal, float perceptual_roughness) { + float3 du = ddx(geometric_normal); + float3 dv = ddy(geometric_normal); - // Boxed equation in section 3.2 "Proposed Error Reduction." - float variance = dot(du, du) + dot(dv, dv); - float sigma = 0.5f; // standard deviation of pixel filter kernel in image space - float Sigma = sigma * sigma * variance; - - // Equation 1 in section 4.2 "Constraint for Conservative Isotropic Filtering" + float variance = _Specular_AA_Variance * (dot(du, du) + dot(dv, dv)); float roughness = perceptual_roughness * perceptual_roughness; - float kappa = 0.18; - roughness = roughness + min(2 * Sigma, kappa); + float kernel_roughness = min(2.0f * variance, _Specular_AA_Threshold); + float square_roughness = saturate(roughness * roughness + kernel_roughness); - return saturate(sqrt(roughness)); + return saturate(sqrt(sqrt(square_roughness))); } void propagateSmoothness(inout Pbr pbr) { - pbr.smoothness = 1.0f - normalFiltering(pbr.normal, 1.0f - pbr.smoothness); + pbr.smoothness = 1.0f - normalFiltering(pbr.geometric_normal, 1.0f - pbr.smoothness); pbr.roughness_perceptual = clamp(1.0f - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); #if defined(_CLEARCOAT) - pbr.cc_roughness = max(MIN_ROUGHNESS, pbr.cc_roughness * pbr.cc_roughness); + pbr.cc_roughness_perceptual = clamp(pbr.cc_roughness_perceptual, MIN_PERCEPTUAL_ROUGHNESS, 1); + pbr.cc_roughness_perceptual = normalFiltering(pbr.geometric_normal, pbr.cc_roughness_perceptual); + pbr.cc_roughness = max(MIN_ROUGHNESS, pbr.cc_roughness_perceptual * pbr.cc_roughness_perceptual); #endif } @@ -181,6 +178,7 @@ Pbr getPbr(v2f i) { Pbr pbr = (Pbr) 0; float3 n = i.normal; + pbr.geometric_normal = n; float3 t = i.tangent.xyz; t = normalize(t - n * dot(n, t)); // Gram-Schmidt to avoid skew float3 b = normalize(cross(n, t)) * i.tangent.w; -- cgit v1.2.3