summaryrefslogtreecommitdiffstats
path: root/pbr.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-03-16 16:22:45 -0700
committeryum <yum.food.vr@gmail.com>2026-03-16 16:22:45 -0700
commit0b42d463db23d2c6eb0b6651486912ffed2f8857 (patch)
tree20fc0398a794429146b7875ae6f655b01ab414de /pbr.cginc
parent1a35d85c623569dd2e61b821bfe3a7f03f99343f (diff)
Fix normal filtering, which fixes both IBL and direct lighting flashing
Diffstat (limited to 'pbr.cginc')
-rwxr-xr-xpbr.cginc28
1 files changed, 13 insertions, 15 deletions
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;