"A low sun in a street canyon leaves the ground unshadowed"
▸ SYMPTOM
- A frame contains zero visible ground shadows even though every shadow flag is correct.
- The light is casting, the cascade split ratio is tuned, and the near NPCs all have
SceneObject.Flags.CastShadows = true. - The cascaded shadow map still costs a large share of the frame while producing nothing on screen.
▸ CAUSE
A golden-hour sun at single-digit elevation puts no direct light on the ground of a street canyon. Nothing standing on that ground casts a visible shadow, and the cascade is billed in full to produce a constant.
Shadow length on flat ground is H / tan(elevation). At 7 degrees that is 8.14 * H, so a 14 m facade throws a 113 m shadow. Only the component across the street blocks the street, which is length * sin(azimuth offset from the street axis).
Worked case: a 25.4 m street with 14 m facades, sun at elevation 7 and azimuth 45 degrees off the street axis, gives an 80 m cross-street shadow against a 12.7 m half-width. That is an overshoot of 6.3x. Every square metre of ground is permanently shaded, all day, everywhere on the map.
This looks exactly like a bug and is not one. On the project that hit this, the cascade measured 65 to 68 per cent of every frame's draws (2.88x at 1600 agents, 3.13x at 2400) while its only on-screen product was the shadow line partway down the facades. Do the arithmetic before touching a renderer flag.
▸ FIX
The fix is the sun angle, and it is a trade, not a free win. For sun to reach the street centreline you need H / tan(elevation) * sin(offset) <= half-width.
- At a 45-degree offset that case needs elevation 38 to 44, a near-noon sun that is not a golden hour.
- At a 12-degree offset it needs only elevation 13 to 16, which still reads low and warm and still rakes the cross facades diagonally.
A small azimuth offset buys far more ground light than a big elevation change, because the offset enters as a sine while the elevation enters as a tangent. Rule of thumb for any low-sun street scene: keep the sun within about 15 degrees of the street axis, or accept that the street floor is a shadow.
▸ WHY IT WORKS
Two engine-side companions are silent on a fully shaded ground.
DirectionalLight.ContactShadowsearns nothing where there is no direct light to occlude.- An ambient authored as a single flat
SkyColorgives shaded ground one constant colour times albedo, which reads as flat and lacking depth. Fix that with anAmbientOcclusioncomponent rather than with any light.
- Published