diff options
| author | yum <yum.food.vr@gmail.com> | 2025-03-14 18:36:01 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-03-14 18:36:03 -0700 |
| commit | df77089d90024f229e4dd27a25a9b97645b614d1 (patch) | |
| tree | a813b1174ec18a75721b581e5335e618e6d64186 /yum_lighting.cginc | |
| parent | 55bbace0f35ca86b4c8f36bbf2ce7d2f1e50bfac (diff) | |
Simplify spherical harmonics
Implement standard SH9 as a learning exercise. Drop poi's fancy SH9
code. Realize that we just want diffuse and lock everything else away
behind a ui-inaccessible #define.
Diffstat (limited to 'yum_lighting.cginc')
| -rw-r--r-- | yum_lighting.cginc | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/yum_lighting.cginc b/yum_lighting.cginc index b8856ed..23e360e 100644 --- a/yum_lighting.cginc +++ b/yum_lighting.cginc @@ -142,13 +142,54 @@ float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir) { return UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
}
+float3 yumSH9(float4 n) {
+#if defined(YUM_SH9_STANDARD)
+ // 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);
+
+ return L0 + L1 + L2;
+#else
+ // On non-photorealistic avatars, simply using the diffuse component looks
+ // better. *shruge*
+ float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
+ return L00;
+#endif
+}
+
float4 getIndirectDiffuse(v2f i, float4 vertexLightColor) {
float4 diffuse = vertexLightColor;
#if defined(FORWARD_BASE_PASS)
#if defined(LIGHTMAP_ON)
diffuse.xyz = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv2));
#else
- diffuse.xyz += max(0, BetterSH9(float4(0, 0, 0, 1)));
+ diffuse.xyz += max(0, yumSH9(float4(0, 0, 0, 1)));
#endif
#endif
return diffuse;
@@ -169,12 +210,7 @@ YumLighting GetYumLighting(v2f i, YumPbr pbr) { light.direct = _LightColor0.rgb;
// TODO filament's spherical harmonics look nicer than this.
// See FilamentLightIndirect.cginc::UnityGI_Irradiance in filamented.
- //ifex _Spherical_Harmonics==0
- light.diffuse = max(0, BetterSH9(float4(i.normal, 1)));
- //endex
- //ifex _Spherical_Harmonics==1
- light.diffuse = max(0, BetterSH9(float4(0, 0, 0, 1)));
- //endex
+ light.diffuse = getIndirectDiffuse(i, /*vertexLightColor=*/0);
#if defined(_MIN_BRIGHTNESS)
light.diffuse = max(_Min_Brightness, light.diffuse);
#endif
|
