summaryrefslogtreecommitdiffstats
path: root/lighting.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-03-11 17:35:46 -0700
committeryum <yum.food.vr@gmail.com>2026-03-11 17:35:46 -0700
commitc36b919595874355c511b2c75ba9797440be09a5 (patch)
tree1328f04615d58591883c2c7d9de60614975846be /lighting.cginc
parentc8cfc043c105a32e1efab341536311277bfc90eb (diff)
Update specular occlusion; always runs now
Diffstat (limited to 'lighting.cginc')
-rwxr-xr-xlighting.cginc32
1 files changed, 12 insertions, 20 deletions
diff --git a/lighting.cginc b/lighting.cginc
index 9ea2052..2e3a79b 100755
--- a/lighting.cginc
+++ b/lighting.cginc
@@ -34,9 +34,10 @@ float4 getDirectLightColorIntensity() {
return float4(_LightColor0.xyz, _LightColor0.w);
}
-float3 getIndirectSpecular(v2f i, float perceptual_roughness, float3 view_dir, float3 reflect_dir) {
+float3 getIndirectSpecular(v2f i, float perceptual_roughness, float3 view_dir, float3 reflect_dir, float3 indirect_diffuse) {
UnityGIInput data = InitialiseUnityGIInput(i.worldPos, view_dir);
float3 env_refl = UnityGI_prefilteredRadiance(data, perceptual_roughness, reflect_dir);
+
return env_refl;
}
@@ -173,35 +174,26 @@ float getAO(v2f i) {
}
float getSpecularAO(v2f i, Pbr pbr, LightData data, float3 reflect_dir) {
- float spec_ao = 1;
-#if defined(_AMBIENT_OCCLUSION) || defined(_BENT_NORMALS)
float ao_vis = 1.0;
#if defined(_AMBIENT_OCCLUSION)
ao_vis = data.common.ao;
#endif
+
+ // Exposure occlusion: derive specular AO from diffuse irradiance magnitude.
+ // When IBL diffuse goes dark, attenuate specular to avoid implausible
+ // reflections. Based on filamented's IrradianceToExposureOcclusion.
+ float exposure_ao = saturate(length(data.indirect.diffuse) / _Exposure_Occlusion);
+ ao_vis *= exposure_ao;
+
#if defined(_BENT_NORMALS)
float3 spec_ao_normal = pbr.bent_normal;
#else
float3 spec_ao_normal = pbr.normal;
#endif
- spec_ao = computeSpecularAO(data.common.NoV, ao_vis, pbr.roughness, spec_ao_normal, -data.indirect.dir);
+ float spec_ao = computeSpecularAO(data.common.NoV, ao_vis, pbr.roughness, spec_ao_normal, -data.indirect.dir);
#if defined(_BENT_NORMALS)
spec_ao = saturate(lerp(1.0, spec_ao, _Bent_Normals_Strength));
#endif
-#endif
-
- // Didn't see a big difference in testbed, so commented out.
- // Bent normals get us most of what we want.
-#if 0
- // Horizon fading
- // https://marmosetco.tumblr.com/post/81245981087
- // The goal is to attenuate anything which points into the mesh.
- // TODO expose fade strength as a parameter.
- float horizon_fade_str = 1.3;
- float horizon_fade = saturate(1.0f + horizon_fade_str * dot(pbr.normal, -reflect_dir));
- horizon_fade *= horizon_fade;
- spec_ao *= horizon_fade;
-#endif
return spec_ao;
}
@@ -259,13 +251,13 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.indirect.double_LoV = saturate(2.0f * indirect_LoV * indirect_LoV - 1.0f);
data.indirect.diffuse = getIndirectDiffuse(i, pbr, data);
- data.indirect.specular = getIndirectSpecular(i, pbr.roughness_perceptual, view_dir, data.indirect.dir);
+ data.indirect.specular = getIndirectSpecular(i, pbr.roughness_perceptual, view_dir, data.indirect.dir, data.indirect.diffuse);
data.common.ao = getAO(i);
data.common.spec_ao = getSpecularAO(i, pbr, data, reflect_dir);
#if defined(_CLEARCOAT)
- data.indirect.specular_cc = getIndirectSpecular(i, pbr.cc_roughness_perceptual, view_dir, dir_cc);
+ data.indirect.specular_cc = getIndirectSpecular(i, pbr.cc_roughness_perceptual, view_dir, dir_cc, data.indirect.diffuse);
#if defined(_CLEARCOAT_MASK)
float cc_mask = _Clearcoat_Mask.Sample(bilinear_clamp_s, i.uv01.xy).r;
data.indirect.specular_cc *= cc_mask;