Quick answer: Sample _MainLightPosition in the fragment stage, not the vertex stage. Or set a global from script (Shader.SetGlobalVector("_SunDirection", ...)) and read it per-pixel. Day/night cycles rotate the light per-frame and vertex caching loses precision.
Day/night cycle rotates the sun. Custom toon shader uses NdotL math against the main light. Lighting looks fine at noon, weird at sunset, broken at night.
The Symptom
Custom-lit objects show wrong shading angles as the directional light rotates. Lighting may freeze, invert, or gradient incorrectly. PBR materials look fine; only the custom shader is wrong.
What Causes This
Sampling main-light position at the vertex stage executes once per vertex, before the fragment runs. The fragment interpolates that vertex value. For static lighting this is fine; for animated directional lights, vertex sampling lags behind the actual light direction by a frame or interpolates between stale corner values.
The Fix
Step 1: Move sample to fragment. In Shader Graph, place the Main Light Direction Custom Function node in the fragment stack. The shader compiles with the call inside the fragment shader.
// HLSL Custom Function
void MainLightDirection_float(out float3 Direction)
{
#ifdef SHADERGRAPH_PREVIEW
Direction = float3(0.5, 0.5, 0.5);
#else
Light L = GetMainLight();
Direction = L.direction;
#endif
}
Step 2: Or use a global.
// In script
[ExecuteAlways]
public class SunPublisher : MonoBehaviour
{
public Light sun;
private static readonly int _id = Shader.PropertyToID("_SunDirection");
void Update()
{
Shader.SetGlobalVector(_id, -sun.transform.forward);
}
}
Sample _SunDirection in the shader (Vector4 property, set via Override Property Declaration to Global). Updated per frame; consistent across all materials that read it.
Verifying
Animate the sun rotation. Custom-lit object shading should track in real time. If shading lags or quantizes, you’re still sampling at vertex.
“Sample in fragment. Or publish a global. Lighting tracks the sun.”
Related Issues
For SRP Batcher incompatible, see SRP Batcher. For Time node frozen, see Time node.
Fragment stage. Per-pixel. Sun follows.