summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-06-30 20:37:47 -0700
committeryum <yum.food.vr@gmail.com>2025-06-30 20:37:47 -0700
commit33a4a6d93f5f6c98cfc1bda95f9d3903310bc511 (patch)
tree5c99afc2344ff09c9c68b20dac18a74e332d0a0f
parent586f15513edd509f6ea7258eca52c1038024ac07 (diff)
add wrapped spherical harmonics
-rw-r--r--yum_brdf.cginc9
-rw-r--r--yum_lighting.cginc50
2 files changed, 42 insertions, 17 deletions
diff --git a/yum_brdf.cginc b/yum_brdf.cginc
index 364a183..daa6793 100644
--- a/yum_brdf.cginc
+++ b/yum_brdf.cginc
@@ -99,10 +99,9 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) {
#if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE)
// Energy conservative wrap diffuse for subsurface scattering
- float wrap_diffuse = saturate((NoL + 0.5) / 2.25);
- Fd *= wrap_diffuse;
+ Fd *= NoL_wrapped_d;
// Apply subsurface color
- Fd *= saturate(_Cloth_Subsurface_Color + NoL);
+ Fd *= saturate(_Cloth_Subsurface_Color + NoL_wrapped_d);
#endif
// Cloth specular BRDF - multiply by PI to match Unity intensities
@@ -110,9 +109,9 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) {
#if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE)
// No need to multiply by NoL when using subsurface scattering
- direct_cloth = (Fd + Fr * NoL) * light.direct * _Cloth_Direct_Multiplier;
+ direct_cloth = (Fd + Fr * NoL_wrapped_s) * light.direct * _Cloth_Direct_Multiplier;
#else
- direct_cloth = (Fd + Fr) * NoL * light.direct * _Cloth_Direct_Multiplier;
+ direct_cloth = (Fd + Fr) * NoL_wrapped_d * light.direct * _Cloth_Direct_Multiplier;
#endif
}
#endif
diff --git a/yum_lighting.cginc b/yum_lighting.cginc
index 56fca90..88e8da7 100644
--- a/yum_lighting.cginc
+++ b/yum_lighting.cginc
@@ -208,24 +208,50 @@ float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) {
L21 * n.x * n.z +
L22 * (n.x * n.x - n.y * n.y);
+#if defined(_WRAPPED_LIGHTING)
+ float wrap_term = _Wrap_NoL_Diffuse_Strength;
+ // 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;
+#else
+ float l1_wrap = 1.0f;
+#endif
+
light.L00 = L00;
- light.L01r = unity_SHAr.xyz;
- light.L01g = unity_SHAg.xyz;
- light.L01b = unity_SHAb.xyz;
+ 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;
#else
LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b);
-#if defined(_SPHERICAL_HARMONICS_L1)
- return LightVolumeEvaluate(n.xyz, light.L00, light.L01r, light.L01g, light.L01b);
-#else
- [branch]
- if (_UdonLightVolumeEnabled) {
- return LightVolumeEvaluate(n.xyz, light.L00, light.L01r, light.L01g, light.L01b);
- } else {
- return LightVolumeEvaluate(n.xyz, light.L00, 0, 0, 0);
- }
+
+#if defined(_WRAPPED_LIGHTING)
+ float wrap_term = _Wrap_NoL_Diffuse_Strength;
+ // Hack. Not energy preserving but sorta close. I think this looks better at fully flat mode.
+ float l1_wrap = 1.0f - wrap_term * 0.75f;
+ light.L01r *= l1_wrap;
+ light.L01g *= l1_wrap;
+ light.L01b *= l1_wrap;
#endif
+
+ return light.L00 + float3(
+ dot(light.L01r, n.xyz),
+ dot(light.L01g, n.xyz),
+ dot(light.L01b, n.xyz));
#endif
}