summaryrefslogtreecommitdiffstats
path: root/lighting.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-02-23 20:20:31 -0800
committeryum <yum.food.vr@gmail.com>2026-02-23 20:20:31 -0800
commit5fa1c0ec5b2b59db3858a7dfe9f4001eeeff8cc9 (patch)
tree5e1d7729e2fe52964c9d7c52aece72b4f2ecb3e5 /lighting.cginc
parent2d205f1f5df12b6e66f6cca1a05152b18d53c0d1 (diff)
Add ambient occlusion & normal filtering
Diffstat (limited to 'lighting.cginc')
-rwxr-xr-xlighting.cginc55
1 files changed, 40 insertions, 15 deletions
diff --git a/lighting.cginc b/lighting.cginc
index 87a3dfc..28ac25b 100755
--- a/lighting.cginc
+++ b/lighting.cginc
@@ -90,9 +90,9 @@ float4 getDirectLightColorIntensity() {
return float4(_LightColor0.xyz, _LightColor0.w);
}
-float3 getIndirectSpecular(v2f i, float roughness, float3 view_dir, float3 reflect_dir) {
+float3 getIndirectSpecular(v2f i, float perceptual_roughness, float3 view_dir, float3 reflect_dir) {
UnityGIInput data = InitialiseUnityGIInput(i.worldPos, view_dir);
- float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
+ float3 env_refl = UnityGI_prefilteredRadiance(data, perceptual_roughness, reflect_dir);
return env_refl;
}
@@ -133,23 +133,42 @@ float3 yumSH9(float4 n, float3 worldPos, inout LightIndirect light) {
dot(light.L01b, n.xyz));
}
- // Geomerics SH evaluation
- // Extract L0 and optionally incorporate part of L2
- float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
- float3 L0L2 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0;
- L0 = L0 + L0L2; // useL2 = true
-
- float3 finalSH;
- finalSH.r = shEvaluateDiffuseL1Geomerics(L0.r, unity_SHAr.xyz, n.xyz);
- finalSH.g = shEvaluateDiffuseL1Geomerics(L0.g, unity_SHAg.xyz, n.xyz);
- finalSH.b = shEvaluateDiffuseL1Geomerics(L0.b, unity_SHAb.xyz, n.xyz);
+ // Unity gives us the first three bands (L0-L2) of SH coefficients as follows:
+ // unity_SHA*.w: L0 coefficients
+ // unity_SHA*.xyz: L1 coefficients
+ // unity_SHB*: first four of the L2 coefficients
+ // unity_SHC: last L2 coefficient
+
+ // Parse out coefficients into a simpler but less efficient format.
+ float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
+ float3 L1_1 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x);
+ float3 L10 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y);
+ float3 L11 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z);
+ float3 L2_2 = float3(unity_SHBr.x, unity_SHBg.x, unity_SHBb.x);
+ float3 L2_1 = float3(unity_SHBr.y, unity_SHBg.y, unity_SHBb.y);
+ float3 L20 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z);
+ float3 L21 = float3(unity_SHBr.w, unity_SHBg.w, unity_SHBb.w);
+ float3 L22 = unity_SHC;
+
+ // Equation 13 from "An Efficient Representation for Irradiance Environment
+ // Maps" by Ramamoorthi and Hanrahan. Note that the order of some
+ // coefficients is different, and normalization constants have been
+ // premultiplied by Unity.
+ float3 L0 = L00;
+ float3 L1 = L1_1 * n.x + L10 * n.y + L11 * n.z;
+ float3 L2 =
+ L2_2 * n.x * n.y +
+ L2_1 * n.y * n.z +
+ L20 * n.z * n.z +
+ L21 * n.x * n.z +
+ L22 * (n.x * n.x - n.y * n.y);
light.L00 = L0;
light.L01r = unity_SHAr.xyz;
light.L01g = unity_SHAg.xyz;
light.L01b = unity_SHAb.xyz;
- return finalSH;
+ return L0 + L1 + L2;
}
float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightIndirect light) {
@@ -157,6 +176,12 @@ float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightIndirect light) {
#if defined(FORWARD_BASE_PASS)
diffuse.xyz += max(0, yumSH9(float4(i.normal, 1.0), i.worldPos, light));
#endif
+
+#if defined(_AMBIENT_OCCLUSION)
+ diffuse.xyz *= lerp(1, _OcclusionMap.Sample(bilinear_repeat_s, i.uv01.xy), 1);
+ //diffuse.xyz = _OcclusionMap.Sample(bilinear_repeat_s, i.uv01.xy);
+#endif
+
return diffuse;
}
@@ -208,9 +233,9 @@ 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.indirect);
- data.indirect.specular = getIndirectSpecular(i, pbr.roughness, view_dir, -data.indirect.dir);
+ data.indirect.specular = getIndirectSpecular(i, pbr.roughness_perceptual, view_dir, -data.indirect.dir);
#if defined(_CLEARCOAT)
- data.indirect.specular_cc = getIndirectSpecular(i, pbr.cc_roughness, view_dir, dir_cc);
+ data.indirect.specular_cc = getIndirectSpecular(i, saturate(sqrt(pbr.cc_roughness)), view_dir, dir_cc);
#if defined(_CLEARCOAT_MASK)
float cc_mask = _Clearcoat_Mask.Sample(bilinear_clamp_s, i.uv01.xy).r;
data.indirect.specular_cc *= cc_mask;