diff options
| author | yum <yum.food.vr@gmail.com> | 2026-02-23 20:20:31 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-02-23 20:20:31 -0800 |
| commit | 5fa1c0ec5b2b59db3858a7dfe9f4001eeeff8cc9 (patch) | |
| tree | 5e1d7729e2fe52964c9d7c52aece72b4f2ecb3e5 /pbr.cginc | |
| parent | 2d205f1f5df12b6e66f6cca1a05152b18d53c0d1 (diff) | |
Add ambient occlusion & normal filtering
Diffstat (limited to 'pbr.cginc')
| -rwxr-xr-x | pbr.cginc | 42 |
1 files changed, 32 insertions, 10 deletions
@@ -26,8 +26,11 @@ struct Pbr { #endif }; -#define MIN_PERCEPTUAL_ROUGHNESS 5e-2f -#define MIN_ROUGHNESS 5e-3f +// From filament: min roughness s.t. MIN_PERCEPTUAL_ROUGHNESS^4 > 0 in target +// precision. We use fp32. The smallest non-subnormal is 2^(-126). The 4th +// root of that is ~3.29 * 10^-10. +#define MIN_PERCEPTUAL_ROUGHNESS (3.3E-10) +#define MIN_ROUGHNESS (1.09E-19) #if defined(_PARALLAX_HEIGHTMAP) float2 parallax_offset(float2 uv, float3 view_dir_world, float3x3 tbn) { @@ -115,10 +118,29 @@ float2 parallax_offset(float2 uv, float3 view_dir_world, float3x3 tbn) { } #endif // _PARALLAX_HEIGHTMAP -// TODO consider normal filtering like filamented +// Tokuyashi and Kaplanyan 2019 "Improved Geometric Specular Antialiasing" +float normalFiltering(float3 normal, float perceptual_roughness) { + float3 du = ddx(normal); + float3 dv = ddy(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 roughness = perceptual_roughness * perceptual_roughness; + float kappa = 0.18; + roughness = roughness + min(2 * Sigma, kappa); + + return sqrt(roughness); +} + void propagateSmoothness(inout Pbr pbr) { - pbr.roughness_perceptual = max(MIN_PERCEPTUAL_ROUGHNESS, 1.0f - pbr.smoothness); - pbr.roughness = max(MIN_ROUGHNESS, pbr.roughness_perceptual * pbr.roughness_perceptual); + pbr.smoothness = 1.0f - normalFiltering(pbr.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); #endif @@ -168,25 +190,25 @@ Pbr getPbr(v2f i) { pbr.objPos = imp.objPos; #endif #else - pbr.albedo = _MainTex.Sample(aniso16_trilinear_repeat_s, uv_parallax * _MainTex_ST.xy + _MainTex_ST.zw); + pbr.albedo = _MainTex.Sample(aniso4_trilinear_repeat_s, uv_parallax * _MainTex_ST.xy + _MainTex_ST.zw); pbr.albedo *= _Color; apply_marble(i.worldPos, pbr.albedo.xyz); - float3 normal_tangent = UnpackNormal(_BumpMap.Sample(aniso16_trilinear_repeat_s, uv_parallax * _BumpMap_ST.xy)); + float3 normal_tangent = UnpackNormal(_BumpMap.Sample(aniso4_trilinear_repeat_s, uv_parallax * _BumpMap_ST.xy)); normal_tangent.xy *= _BumpScale; #if defined(_DETAILS) float2 detail_uv = get_uv_by_channel(i, _Details_UV_Channel); - float3 detail_normal = UnpackNormal(_DetailNormalMap.Sample(aniso16_trilinear_repeat_s, detail_uv * _DetailNormalMap_ST.xy)); + float3 detail_normal = UnpackNormal(_DetailNormalMap.Sample(aniso4_trilinear_repeat_s, detail_uv * _DetailNormalMap_ST.xy)); detail_normal.xy *= _DetailNormalMapScale; - float detail_mask = _DetailMask.Sample(aniso16_trilinear_repeat_s, detail_uv * _DetailMask_ST.xy).r; + float detail_mask = _DetailMask.Sample(aniso4_trilinear_repeat_s, detail_uv * _DetailMask_ST.xy).r; detail_normal.xy *= detail_mask; normal_tangent = blendNormalsHill12(normal_tangent, detail_normal); #endif pbr.normal = normalize(mul(normal_tangent, pbr.tbn)); - float4 metallic_gloss = _MetallicGlossMap.Sample(aniso16_trilinear_repeat_s, uv_parallax * _MetallicGlossMap_ST.xy); + float4 metallic_gloss = _MetallicGlossMap.Sample(aniso4_trilinear_repeat_s, uv_parallax * _MetallicGlossMap_ST.xy); pbr.smoothness = metallic_gloss.a * _Glossiness; pbr.metallic = metallic_gloss.r * _Metallic; #endif // _IMPOSTORS |
