summaryrefslogtreecommitdiffstats
path: root/yum_lighting.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-06-13 17:59:00 -0700
committeryum <yum.food.vr@gmail.com>2025-06-13 17:59:00 -0700
commita9dbbfa1488a9ec3bd772fc9847888502f49a65e (patch)
tree2930432ee795faff97b81c6261c2160a37125048 /yum_lighting.cginc
parentf639117b1f743ab2941667b32b190dd1e715d4a5 (diff)
Fix some filamented inconsistencies
Diffstat (limited to 'yum_lighting.cginc')
-rw-r--r--yum_lighting.cginc626
1 files changed, 330 insertions, 296 deletions
diff --git a/yum_lighting.cginc b/yum_lighting.cginc
index dabc148..d1cf779 100644
--- a/yum_lighting.cginc
+++ b/yum_lighting.cginc
@@ -1,296 +1,330 @@
-#ifndef __YUM_LIGHTING_INC
-#define __YUM_LIGHTING_INC
-
-#include "UnityCG.cginc"
-#include "AutoLight.cginc"
-#include "UnityPBSLighting.cginc"
-#include "UnityLightingCommon.cginc"
-
-#include "features.cginc"
-#include "LightVolumes.cginc"
-#include "poi.cginc"
-#include "yum_pbr.cginc"
-
-// fucking kill me
-#ifndef __LTCGI_INC
-#define __LTCGI_INC
-
-#include "features.cginc"
-
-#if defined(_LTCGI)
-struct ltcgi_acc {
- float3 diffuse;
- float3 specular;
-};
-
-#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc"
-
-void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output);
-void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output);
-
-#define LTCGI_V2_CUSTOM_INPUT ltcgi_acc
-#define LTCGI_V2_DIFFUSE_CALLBACK ltcgi_cb_diffuse
-#define LTCGI_V2_SPECULAR_CALLBACK ltcgi_cb_specular
-
-#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc"
-void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output) {
- acc.diffuse += output.intensity * output.color * _LTCGI_DiffuseColor;
-}
-void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output) {
- acc.specular += output.intensity * output.color * _LTCGI_SpecularColor;
-}
-#endif // _LTCGI
-
-#endif // __LTCGI_INC
-
-struct YumLighting {
- float3 view_dir;
- float3 dir;
- float3 direct;
- float3 diffuse;
- float diffuse_luminance;
- float3 specular;
- float NoL;
-#if defined(_WRAPPED_LIGHTING)
- float NoL_wrapped_s; // specular
- float NoL_wrapped_d; // diffuse
-#endif
- float attenuation;
- float3 L00;
- float3 L01r;
- float3 L01g;
- float3 L01b;
-};
-
-float getShadowAttenuation(v2f i)
-{
- float attenuation;
- // This whole block is yoinked from AutoLight.cginc. I needed a way to
- // control shadow strength so I had to duplicate the code.
-#if defined(DIRECTIONAL_COOKIE)
- DECLARE_LIGHT_COORD(i, i.worldPos);
- float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
- attenuation = tex2D(_LightTexture0, lightCoord).w;
-#elif defined(POINT_COOKIE)
- DECLARE_LIGHT_COORD(i, i.worldPos);
- float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
- attenuation = tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).r *
- texCUBE(_LightTexture0, lightCoord).w;
-#elif defined(DIRECTIONAL)
- float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
- attenuation = 1;
-#elif defined(SPOT)
- DECLARE_LIGHT_COORD(i, i.worldPos);
- float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
- attenuation = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) *
- UnitySpotAttenuate(lightCoord.xyz);
-#elif defined(POINT)
- unityShadowCoord3 lightCoord =
- mul(unity_WorldToLight, unityShadowCoord4(i.worldPos, 1)).xyz;
- float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
- attenuation = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r;
-#else
- float shadow = 1;
- attenuation = 1;
-#endif
- attenuation *= lerp(1, shadow, _Shadow_Strength);
- return attenuation;
-}
-
-float3 getDirectLightDirection(v2f i) {
-#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT)
- return normalize((_WorldSpaceLightPos0 - i.worldPos).xyz);
-#else
- return _WorldSpaceLightPos0;
-#endif
-}
-
-float GetLodRoughness(float roughness) {
- return roughness * (1.7 - 0.7 * roughness);
-}
-
-float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_luminance) {
- float roughness = GetLodRoughness(pbr.roughness_perceptual);
- float3 reflect_dir = reflect(-view_dir, pbr.normal);
-
- UnityGIInput data;
- data.worldPos = i.worldPos;
- data.worldViewDir = view_dir;
- data.probeHDR[0] = unity_SpecCube0_HDR;
- data.probeHDR[1] = unity_SpecCube1_HDR;
-#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
- data.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
-#endif
-#ifdef UNITY_SPECCUBE_BOX_PROJECTION
- data.boxMax[0] = unity_SpecCube0_BoxMax;
- data.probePosition[0] = unity_SpecCube0_ProbePosition;
- data.boxMax[1] = unity_SpecCube1_BoxMax;
- data.boxMin[1] = unity_SpecCube1_BoxMin;
- data.probePosition[1] = unity_SpecCube1_ProbePosition;
-#endif
-
- const float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
-
-#if defined(_FALLBACK_CUBEMAP)
- // Check if there's no valid scene cubemap
- float3 canned_refl = env_refl;
- if (!SceneHasReflections() || _Fallback_Cubemap_Force) {
- // Set up data for fallback sampling similar to Unity's system
- half3 reflectVector = reflect(-view_dir, pbr.normal);
-
- #ifdef UNITY_SPECCUBE_BOX_PROJECTION
- reflectVector = BoxProjectedCubemapDirection(reflectVector, data.worldPos, /*probe_position=*/0, /*box_min=*/-1, /*box_max=*/1);
- #endif
-
- half mip = roughness * UNITY_SPECCUBE_LOD_STEPS;
- float4 envSample = UNITY_SAMPLE_TEXCUBE_LOD(_Fallback_Cubemap, reflectVector, mip);
- canned_refl = DecodeHDR(envSample, _Fallback_Cubemap_HDR) * _Fallback_Cubemap_Brightness * diffuse_luminance;
- }
-#endif
-
-#if defined(_FALLBACK_CUBEMAP_LIMIT_METALLIC)
- return lerp(env_refl, canned_refl, pbr.metallic);
-#elif defined(_FALLBACK_CUBEMAP)
- return canned_refl;
-#else
- return env_refl;
-#endif
-}
-
-float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) {
-#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);
-
- light.L00 = L00;
- light.L01r = unity_SHAr.xyz;
- light.L01g = unity_SHAg.xyz;
- light.L01b = unity_SHAb.xyz;
-
- return L0 + L1 + L2;
-#elif 1
- // Light volumes. We omit the L01 contribution since flat shading looks
- // better on avatars.
- LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b);
- return LightVolumeEvaluate(n.xyz, light.L00,
- _UdonLightVolumeEnabled ? light.L01r : 0,
- _UdonLightVolumeEnabled ? light.L01g : 0,
- _UdonLightVolumeEnabled ? light.L01b : 0);
-#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);
-
- light.L00 = L00;
- light.L01r = unity_SHAr.xyz;
- light.L01g = unity_SHAg.xyz;
- light.L01b = unity_SHAb.xyz;
-
- return L00;
-#endif
-}
-
-float4 getIndirectDiffuse(v2f i, float4 vertexLightColor,
- inout YumLighting light) {
- float4 diffuse = vertexLightColor;
-#if defined(FORWARD_BASE_PASS)
-#if defined(LIGHTMAP_ON)
- diffuse.xyz = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv01.zw));
-#else
- diffuse.xyz += max(0, yumSH9(float4(i.normal, 0), i.worldPos, light));
-#endif
-#endif
- return diffuse;
-}
-
-YumLighting GetYumLighting(v2f i, YumPbr pbr) {
- YumLighting light = (YumLighting) 0;
-
- // normalize has no visibile impact in test scene
- light.view_dir = -normalize(i.eyeVec.xyz);
-
- light.dir = getDirectLightDirection(i);
-
- light.direct = _LightColor0.rgb;
- // TODO filament's spherical harmonics look nicer than this.
- // See FilamentLightIndirect.cginc::UnityGI_Irradiance in filamented.
- light.diffuse = getIndirectDiffuse(i, /*vertexLightColor=*/0, light);
-#if defined(_MIN_BRIGHTNESS)
- light.diffuse = max(_Min_Brightness, light.diffuse);
-#endif
-
- light.diffuse_luminance = luminance(light.diffuse);
- light.specular = getIndirectSpecular(i, pbr, light.view_dir, light.diffuse_luminance);
-
-#if defined(_LTCGI)
- ltcgi_acc acc = (ltcgi_acc) 0;
- LTCGI_Contribution(
- acc,
- i.worldPos,
- pbr.normal,
- light.view_dir,
- pbr.roughness_perceptual,
- 0);
- light.diffuse += acc.diffuse * _LTCGI_Strength;
- light.specular += acc.specular * _LTCGI_Strength;
-#endif
-
-#if defined(_QUANTIZE_SPECULAR)
- float specular_luminance = luminance(light.specular);
- light.specular = light.specular * floor(specular_luminance * _Quantize_Specular_Steps) / _Quantize_Specular_Steps;
-#endif
-#if defined(_QUANTIZE_DIFFUSE)
- light.diffuse = light.diffuse * floor(light.diffuse_luminance * _Quantize_Diffuse_Steps) / _Quantize_Diffuse_Steps;
- light.diffuse_luminance = luminance(light.diffuse);
-#endif
-
-#if defined(_BRIGHTNESS_CONTROL)
- light.direct *= _Brightness_Multiplier;
- light.diffuse *= _Brightness_Multiplier;
- light.specular *= _Brightness_Multiplier;
-#endif
-
- light.NoL = dot(pbr.normal, light.dir);
-#if defined(_QUANTIZE_NOL)
- light.NoL = floor(light.NoL * _Quantize_NoL_Steps) / _Quantize_NoL_Steps;
-#endif
-#if defined(_WRAPPED_LIGHTING)
- light.NoL_wrapped_s = saturate(wrapNoL(light.NoL, _Wrap_NoL_Specular_Strength));
- light.NoL_wrapped_d = saturate(wrapNoL(light.NoL, _Wrap_NoL_Diffuse_Strength));
-#endif
- light.NoL = saturate(light.NoL);
-
- light.attenuation = getShadowAttenuation(i);
-
- return light;
-}
-
-#endif // __YUM_LIGHTING_INC
-
+#ifndef __YUM_LIGHTING_INC
+#define __YUM_LIGHTING_INC
+
+#include "UnityCG.cginc"
+#include "AutoLight.cginc"
+#include "UnityPBSLighting.cginc"
+#include "UnityLightingCommon.cginc"
+
+#include "features.cginc"
+#include "LightVolumes.cginc"
+#include "poi.cginc"
+#include "yum_pbr.cginc"
+
+// fucking kill me
+#ifndef __LTCGI_INC
+#define __LTCGI_INC
+
+#include "features.cginc"
+
+#if defined(_LTCGI)
+struct ltcgi_acc {
+ float3 diffuse;
+ float3 specular;
+};
+
+#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc"
+
+void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output);
+void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output);
+
+#define LTCGI_V2_CUSTOM_INPUT ltcgi_acc
+#define LTCGI_V2_DIFFUSE_CALLBACK ltcgi_cb_diffuse
+#define LTCGI_V2_SPECULAR_CALLBACK ltcgi_cb_specular
+
+#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc"
+void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output) {
+ acc.diffuse += output.intensity * output.color * _LTCGI_DiffuseColor;
+}
+void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output) {
+ acc.specular += output.intensity * output.color * _LTCGI_SpecularColor;
+}
+#endif // _LTCGI
+
+#endif // __LTCGI_INC
+
+struct YumLighting {
+ float3 view_dir;
+ float3 dir;
+ float3 direct;
+ float3 diffuse;
+ float diffuse_luminance;
+ float3 specular;
+ float NoL;
+#if defined(_WRAPPED_LIGHTING)
+ float NoL_wrapped_s; // specular
+ float NoL_wrapped_d; // diffuse
+#endif
+ float attenuation;
+ float3 L00;
+ float3 L01r;
+ float3 L01g;
+ float3 L01b;
+ float occlusion;
+ Light derivedLight;
+};
+
+float getShadowAttenuation(v2f i)
+{
+ float attenuation;
+ // This whole block is yoinked from AutoLight.cginc. I needed a way to
+ // control shadow strength so I had to duplicate the code.
+#if defined(DIRECTIONAL_COOKIE)
+ DECLARE_LIGHT_COORD(i, i.worldPos);
+ float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
+ attenuation = tex2D(_LightTexture0, lightCoord).w;
+#elif defined(POINT_COOKIE)
+ DECLARE_LIGHT_COORD(i, i.worldPos);
+ float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
+ attenuation = tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).r *
+ texCUBE(_LightTexture0, lightCoord).w;
+#elif defined(DIRECTIONAL)
+ float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
+ attenuation = 1;
+#elif defined(SPOT)
+ DECLARE_LIGHT_COORD(i, i.worldPos);
+ float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
+ attenuation = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) *
+ UnitySpotAttenuate(lightCoord.xyz);
+#elif defined(POINT)
+ unityShadowCoord3 lightCoord =
+ mul(unity_WorldToLight, unityShadowCoord4(i.worldPos, 1)).xyz;
+ float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos);
+ attenuation = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r;
+#else
+ float shadow = 1;
+ attenuation = 1;
+#endif
+ attenuation *= lerp(1, shadow, _Shadow_Strength);
+ return attenuation;
+}
+
+float3 getDirectLightDirection(v2f i) {
+#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT)
+ return normalize((_WorldSpaceLightPos0 - i.worldPos).xyz);
+#else
+ return _WorldSpaceLightPos0;
+#endif
+}
+
+float GetLodRoughness(float roughness) {
+ return roughness * (1.7 - 0.7 * roughness);
+}
+
+float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_luminance) {
+ float roughness = GetLodRoughness(pbr.roughness_perceptual);
+ float3 reflect_dir = reflect(-view_dir, pbr.normal);
+
+ UnityGIInput data;
+ data.worldPos = i.worldPos;
+ data.worldViewDir = view_dir;
+ data.probeHDR[0] = unity_SpecCube0_HDR;
+ data.probeHDR[1] = unity_SpecCube1_HDR;
+#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
+ data.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
+#endif
+#ifdef UNITY_SPECCUBE_BOX_PROJECTION
+ data.boxMax[0] = unity_SpecCube0_BoxMax;
+ data.probePosition[0] = unity_SpecCube0_ProbePosition;
+ data.boxMax[1] = unity_SpecCube1_BoxMax;
+ data.boxMin[1] = unity_SpecCube1_BoxMin;
+ data.probePosition[1] = unity_SpecCube1_ProbePosition;
+#endif
+
+ const float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
+
+#if defined(_FALLBACK_CUBEMAP)
+ // Check if there's no valid scene cubemap
+ float3 canned_refl = env_refl;
+ if (!SceneHasReflections() || _Fallback_Cubemap_Force) {
+ // Set up data for fallback sampling similar to Unity's system
+ half3 reflectVector = reflect(-view_dir, pbr.normal);
+
+ #ifdef UNITY_SPECCUBE_BOX_PROJECTION
+ reflectVector = BoxProjectedCubemapDirection(reflectVector, data.worldPos, /*probe_position=*/0, /*box_min=*/-1, /*box_max=*/1);
+ #endif
+
+ half mip = roughness * UNITY_SPECCUBE_LOD_STEPS;
+ float4 envSample = UNITY_SAMPLE_TEXCUBE_LOD(_Fallback_Cubemap, reflectVector, mip);
+ canned_refl = DecodeHDR(envSample, _Fallback_Cubemap_HDR) * _Fallback_Cubemap_Brightness * diffuse_luminance;
+ }
+#endif
+
+#if defined(_FALLBACK_CUBEMAP_LIMIT_METALLIC)
+ return lerp(env_refl, canned_refl, pbr.metallic);
+#elif defined(_FALLBACK_CUBEMAP)
+ return canned_refl;
+#else
+ return env_refl;
+#endif
+}
+
+float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) {
+#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);
+
+ light.L00 = L00;
+ light.L01r = unity_SHAr.xyz;
+ light.L01g = unity_SHAg.xyz;
+ light.L01b = unity_SHAb.xyz;
+
+ return L0 + L1 + L2;
+#elif 1
+ // Light volumes. We omit the L01 contribution since flat shading looks
+ // better on avatars.
+ LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b);
+ return LightVolumeEvaluate(n.xyz, light.L00,
+ _UdonLightVolumeEnabled ? light.L01r : 0,
+ _UdonLightVolumeEnabled ? light.L01g : 0,
+ _UdonLightVolumeEnabled ? light.L01b : 0);
+#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);
+
+ light.L00 = L00;
+ light.L01r = unity_SHAr.xyz;
+ light.L01g = unity_SHAg.xyz;
+ light.L01b = unity_SHAb.xyz;
+
+ return L00;
+#endif
+}
+
+float3 SubtractMainLightWithRealtimeAttenuationFromLightmap(float3 lightmap, float attenuation, float4 bakedColorTex, float3 normalWorld) {
+ float3 shadowColor = unity_ShadowColor.rgb;
+ float shadowStrength = _LightShadowData.x;
+
+ // Calculate estimated light contribution that should be shadowed
+ float ndotl = saturate(dot(normalWorld, _WorldSpaceLightPos0.xyz));
+ float3 estimatedLightContributionMaskedByInverseOfShadow = ndotl * (1.0 - attenuation) * _LightColor0.rgb;
+ float3 subtractedLightmap = lightmap - estimatedLightContributionMaskedByInverseOfShadow;
+
+ // Apply shadow color and strength
+ float3 realtimeShadow = max(subtractedLightmap, shadowColor);
+ realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
+
+ // Pick darkest color
+ return min(lightmap, realtimeShadow);
+}
+
+YumLighting GetYumLighting(v2f i, YumPbr pbr) {
+ YumLighting light = (YumLighting) 0;
+
+ // normalize has no visibile impact in test scene
+ light.view_dir = -normalize(i.eyeVec.xyz);
+
+ light.dir = getDirectLightDirection(i);
+
+ light.direct = _LightColor0.rgb;
+
+ // Calculate attenuation first, before diffuse lighting
+#if defined(LIGHTMAP_ON)
+ light.attenuation = 1;
+#else
+ light.attenuation = getShadowAttenuation(i);
+#endif
+
+ // Use filamented's comprehensive irradiance calculation
+ float occlusion;
+ Light derivedLight;
+ float3 tangentNormal = mul(pbr.normal, transpose(float3x3(i.tangent, i.binormal, i.normal)));
+ float3x3 tangentToWorld = float3x3(i.tangent, i.binormal, i.normal);
+
+ light.diffuse = UnityGI_Irradiance(
+ pbr.normal, // worldNormal
+ i.worldPos, // worldPos
+ float4(i.uv01.zw, 0, 0), // lightmapUV (xy = uv0, zw = uv1)
+ float3(0,0,0), // ambient (will be calculated internally)
+ light.attenuation, // attenuation
+ tangentNormal, // tangentNormal
+ tangentToWorld, // tangentToWorld
+ #if defined(USING_BAKERY_VERTEXLMSH)
+ // You'll need to add these to your v2f if using Bakery vertex SH
+ i.bakeryVertexSH,
+ #elif defined(USING_BAKERY_VERTEXLMDIR)
+ // You'll need to add this to your v2f if using Bakery vertex directional
+ i.bakeryVertexDir,
+ #endif
+ occlusion, // out occlusion
+ derivedLight // out Light
+ );
+
+#if defined(_MIN_BRIGHTNESS)
+ light.diffuse = max(_Min_Brightness, light.diffuse);
+#endif
+
+ light.diffuse_luminance = luminance(light.diffuse);
+ light.specular = getIndirectSpecular(i, pbr, light.view_dir, light.diffuse_luminance);
+
+#if defined(_LTCGI)
+ ltcgi_acc acc = (ltcgi_acc) 0;
+ LTCGI_Contribution(
+ acc,
+ i.worldPos,
+ pbr.normal,
+ light.view_dir,
+ pbr.roughness_perceptual,
+ 0);
+ light.diffuse += acc.diffuse * _LTCGI_Strength;
+ light.specular += acc.specular * _LTCGI_Strength;
+#endif
+
+#if defined(_QUANTIZE_SPECULAR)
+ float specular_luminance = luminance(light.specular);
+ light.specular = light.specular * floor(specular_luminance * _Quantize_Specular_Steps) / _Quantize_Specular_Steps;
+#endif
+#if defined(_QUANTIZE_DIFFUSE)
+ light.diffuse = light.diffuse * floor(light.diffuse_luminance * _Quantize_Diffuse_Steps) / _Quantize_Diffuse_Steps;
+ light.diffuse_luminance = luminance(light.diffuse);
+#endif
+
+#if defined(_BRIGHTNESS_CONTROL)
+ light.direct *= _Brightness_Multiplier;
+ light.diffuse *= _Brightness_Multiplier;
+ light.specular *= _Brightness_Multiplier;
+#endif
+
+ light.NoL = dot(pbr.normal, light.dir);
+#if defined(_QUANTIZE_NOL)
+ light.NoL = floor(light.NoL * _Quantize_NoL_Steps) / _Quantize_NoL_Steps;
+#endif
+#if defined(_WRAPPED_LIGHTING)
+ light.NoL_wrapped_s = saturate(wrapNoL(light.NoL, _Wrap_NoL_Specular_Strength));
+ light.NoL_wrapped_d = saturate(wrapNoL(light.NoL, _Wrap_NoL_Diffuse_Strength));
+#endif
+ light.NoL = saturate(light.NoL);
+
+ return light;
+}
+
+#endif // __YUM_LIGHTING_INC
+