diff options
| author | yum <yum.food.vr@gmail.com> | 2025-08-08 15:56:32 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-08-08 15:56:32 -0700 |
| commit | 310dbc3a5393635e08faf78ddf47c57a37524d4b (patch) | |
| tree | e00098d68266ed5125b7f167df6583db96313b63 | |
| parent | 814d4cd95aebb79eabdf4ab31bf9fd7a093e9cef (diff) | |
use standard sh9 when light volumes not present
| -rw-r--r-- | brdf.cginc | 2 | ||||
| -rw-r--r-- | lighting.cginc | 70 |
2 files changed, 67 insertions, 5 deletions
@@ -108,6 +108,7 @@ float4 brdf(Pbr pbr, LightData data) { } // Indirect +#if defined(FORWARD_BASE_PASS) if (true) { float remainder = 1.0f; #if defined(_CLEARCOAT) @@ -127,6 +128,7 @@ float4 brdf(Pbr pbr, LightData data) { float3 indirect_diffuse = Fd * remainder * pbr.albedo.xyz * data.indirect.diffuse; diffuse += indirect_diffuse; } +#endif return float4(diffuse + specular, 1); } diff --git a/lighting.cginc b/lighting.cginc index 66b7220..5055798 100644 --- a/lighting.cginc +++ b/lighting.cginc @@ -98,11 +98,71 @@ float3 getIndirectSpecular(v2f i, float roughness, float3 view_dir, float3 refle } float3 yumSH9(float4 n, float3 worldPos, inout LightIndirect light) { - LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b); - return light.L00 + float3( - dot(light.L01r, n.xyz), - dot(light.L01g, n.xyz), - dot(light.L01b, n.xyz)); + [branch] + if (_UdonLightVolumeEnabled) { + LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b); + return light.L00 + float3( + dot(light.L01r, n.xyz), + dot(light.L01g, n.xyz), + dot(light.L01b, n.xyz)); + } + + // No light volumes - use SH9 + // 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); + + // TODO expose this as a parameter + float wrap_term = 0.0f; + // Original coefficients: 1, 2/3, 1/4. + // Wrapped coefficients: 1, (2-w)/3, ((1-w)^2)/4. + + // Setting w=0, the l1 band is: + // (2-w)/3 = 2/3 + // 2-w = 2 + // 1-w/2 = 1 + float l1_wrap = 1.0f - wrap_term * 0.75f; + L1 *= l1_wrap; + + // The l2 band is: + // ((1-w)^2)/4 = 1/4 + // (1-w)^2 = 1 + float l2_wrap = (1.0f-wrap_term); + l2_wrap *= l2_wrap; + L2 *= l2_wrap; + + light.L00 = L00; + light.L01r = unity_SHAr.xyz * l1_wrap; + light.L01g = unity_SHAg.xyz * l1_wrap; + light.L01b = unity_SHAb.xyz * l1_wrap; + + return L0 + L1 + L2; } float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightIndirect light) { |
