// Emissive-Gloam — the LANTERN "true vs false light" master shader. // One shader is the whole palette rule: hue = warm(ours)/cold(gloam)/lure; and the // load-bearing readability channel is CADENCE — _FlickerAmount 0 = STEADY (true light), // >0 = guttering FALSE light. Flicker lives in-shader (uses _Time), so it needs no script // and reads in edit + play. HDR emission so URP Bloom catches it. Unlit: these are glows. Shader "ProjectM/EmissiveGloam" { Properties { [HDR] _EmissionColor ("Emission (HDR)", Color) = (0.1, 0.8, 0.5, 1) _FlickerAmount ("Flicker Amount (0=steady/true, 1=false)", Range(0,1)) = 0.0 _FlickerSpeed ("Flicker Speed", Float) = 6.0 _Seed ("Per-material phase seed", Float) = 0.0 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" } Pass { Name "EmissiveGloamUnlit" Tags { "LightMode"="UniversalForward" } HLSLPROGRAM // DOTS instancing (2026-08-06 audit, finding M8): this shader is bound to M_Drowner_EyeGlow on // EnemyDrowner.prefab — a baked GHOST prefab, so Entities Graphics renders it through // BatchRendererGroup, which feeds per-instance transforms via DOTS instancing. Without these three // lines the eyes do not get correct instance data. Its skinned sibling // (EmissiveGloamSkinned.shader) has carried them since 07-16; this one was simply missed, and a murk // scene hides the symptom (CLAUDE.md: "a dark-lit screenshot MASKS material bugs"). #pragma target 4.5 #pragma vertex vert #pragma fragment frag #pragma multi_compile _ DOTS_INSTANCING_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionHCS : SV_POSITION; }; CBUFFER_START(UnityPerMaterial) half4 _EmissionColor; half _FlickerAmount; half _FlickerSpeed; half _Seed; CBUFFER_END Varyings vert (Attributes IN) { UNITY_SETUP_INSTANCE_ID(IN); Varyings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); return OUT; } half4 frag (Varyings IN) : SV_Target { float t = _Time.y * _FlickerSpeed + _Seed; // layered sines -> an organic guttering wave in [-1,1] float wave = 0.6 * sin(t) + 0.4 * sin(t * 2.37 + 1.3); // f = 1 when steady (_FlickerAmount==0); dips toward (1-_FlickerAmount) as it gutters float f = 1.0 - _FlickerAmount * (0.5 - 0.5 * wave); return half4(_EmissionColor.rgb * f, 1.0); } ENDHLSL } // DepthOnly (2026-08-06 audit, finding L-shader): without it these glows are absent from URP's depth // texture, so soft particles (marine snow), SSAO and depth-of-field punch straight through them. Costs // nothing today with two materials; would be a visible bug the moment Emissive-Gloam becomes "every glow // in the game", which is the A2 variant plan. Pass { Name "DepthOnly" Tags { "LightMode"="DepthOnly" } ZWrite On ColorMask R HLSLPROGRAM #pragma target 4.5 #pragma vertex depthVert #pragma fragment depthFrag #pragma multi_compile _ DOTS_INSTANCING_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct DepthAttributes { float4 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct DepthVaryings { float4 positionHCS : SV_POSITION; }; DepthVaryings depthVert (DepthAttributes IN) { UNITY_SETUP_INSTANCE_ID(IN); DepthVaryings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); return OUT; } half depthFrag (DepthVaryings IN) : SV_Target { return 0; } ENDHLSL } } Fallback Off }