rendering-shadows

star 1

2D sprite cast-shadow system - Sprite-Lit-ShadowCaster shader, per-prefab opt-in, DayNightCycle-driven shadow strength, interior ShadowsOnlyRoof occluders.

Silac1995 By Silac1995 schedule Updated 4/19/2026

name: rendering/shadows description: 2D sprite cast-shadow system - Sprite-Lit-ShadowCaster shader, per-prefab opt-in, LightingDirector/LightingProfileSO-driven shadow strength, interior ShadowsOnlyRoof occluders.

Rendering - Shadows

Real URP directional-light cast shadows for every 2D sprite in the 3D world. Rotates with the sun driven by LightingDirector (which absorbed and replaced the old DayNightCycle.cs in the 2026-06-12 lighting rework — see .agent/skills/lighting/SKILL.md). Survives the Spine 2D migration without interface changes.

When to use this skill

  • Adding shadow casting to a new sprite prefab (character, tree, furniture, prop).
  • Modifying the shadow-casting shader, material, or URP asset configuration.
  • Setting up / authoring a new interior prefab and its ShadowsOnlyRoof child.
  • Debugging shadow acne, Peter-Panning, or cascade popping.
  • Wiring per-object shadow behaviour from an ItemSO.CastsShadow override.

Components

  • Shader: Assets/Shaders/Sprite-Lit-ShadowCaster.shader - URP Forward pass + alpha-tested ShadowCaster pass.
  • Materials:
    • Assets/Materials/Sprites/DefaultSpriteShadowCaster.mat - default (_Cutoff = 0.5).
    • Assets/Materials/Sprites/SmallPropShadowCaster.mat - variant with _Cutoff = 0.7 for rings/potions.
  • Per-prefab flag: Renderer.shadowCastingMode = On + material swap. Characters, trees, furniture, props.
  • ItemSO override: ItemSO.CastsShadow (default true) drives WorldItem.ApplyShadowCastingFromItemSO() at runtime.
  • Sun hook: the ShadowStrength AnimationCurve on LightingProfileSO (Assets/Resources/Data/Lighting/DefaultLightingProfile.asset), evaluated per frame by LightingDirector.ApplySun (parallel to the SunIntensity curve). Decoupled intentionally so dawn/dusk can run dim-sun + dramatic-shadows. (Was DayNightCycle._shadowStrengthCurve before 2026-06-12.)
  • Received-shadow distance fade: handled inside the stylized-lit shaders via the 3-arg GetMainLight(shadowCoord, positionWS, half4(1,1,1,1)) overload — the 1-arg overload hard-cuts shadows at the last cascade edge instead of fading over the shadow distance.
  • Indoor occluder: Each interior prefab has a ShadowsOnlyRoof child (plane with ShadowCastingMode.ShadowsOnly), sized inline to the interior footprint + shallow-sun margin.
  • URP config: PC_RPAsset + Mobile_RPAsset - 2 cascades, 0.4 split, 80u distance, Soft Cascades On.

How to add shadows to a new prefab

  1. Swap its SpriteRenderer.sharedMaterial to DefaultSpriteShadowCaster (or SmallPropShadowCaster if the sprite is small/thin).
  2. Set shadowCastingMode = On, receiveShadows = true.
  3. For Spine characters: use a Spine-Skeleton-Lit-ZWrite material instead, same two flags on the SkeletonAnimation.MeshRenderer.
  4. For items: set ItemSO.castsShadow on the ItemSO asset (default true; flip false for noisy small sprites).

How to author a new interior prefab roof

  1. Create Empty Child under the interior prefab's root, named ShadowsOnlyRoof.
  2. Add MeshFilter (Plane primitive) + MeshRenderer.
  3. Material: DefaultSpriteShadowCaster (any material works - the quad is shadow-only, visible output is culled).
  4. MeshRenderer.shadowCastingMode = ShadowsOnly, receiveShadows = false.
  5. Position at roof height above the floor (~4.2u for a standard 2.5x-human-height interior).
  6. Rotation X = 90 (plane faces down).
  7. Scale X/Z = interior footprint + shallow-sun margin (e.g. 10x10u interior -> scale 14x14).

Dependencies

  • URP 17.3 (Universal Render Pipeline).
  • LightingDirector.cs + LightingProfileSO + TimeManager.cs (sun rotation + shadow strength + time-of-day). DayNightCycle.cs is DELETED (absorbed by LightingDirector, 2026-06-12).
  • Spine 2D (forward-compat): Spine-Skeleton-Lit-ZWrite.shader already in project.

Integration points

  • CharacterVisual - untouched. Shadow is a pass on the material the renderer already holds.
  • ICharacterVisual - untouched. Shadow logic never touches gameplay code.
  • FurnitureInteractable - untouched. Pure prefab setup.
  • WorldItem - consumes ItemSO.CastsShadow in Initialize().

Multiplayer

No networked surface. Shadows are per-client rendering. TimeManager.CurrentTime01 is already shared, so all clients compute the same sun direction - shadows are implicitly consistent across Host <-> Client, Client <-> Client, Host/Client <-> NPC.

Save / load

Zero surface. Pure visual, no serialization.

Known gotchas

  • No DepthOnly pass in the shader. The sprite shader has only ForwardLit + ShadowCaster. If the project ever enables SSAO or any URP screen-space effect that relies on the camera depth prepass, sprites will not write to the depth texture and silhouettes will disappear from the depth-dependent effect. Fix when needed: add a standard URP DepthOnly pass (10-line modeled on URP Unlit) with the same alpha clip as the ShadowCaster pass.
  • ShadowsOnlyRoof default size is 14x14. Interior prefabs larger than ~10u footprint will leak sun at shallow dawn/dusk angles. Verify per-interior in Play Mode at TimeManager.CurrentTime01 = 0.25 and 0.75; resize the child quad in the Inspector where needed.

Open items (tunable after playtest)

  • Light.shadowNormalBias defaults to 0.8 - tune 0.5-1.5 if acne or Peter-Panning appears.
  • DefaultSpriteShadowCaster._Cutoff = 0.5 / SmallPropShadowCaster._Cutoff = 0.7 - artists can override per material if a specific sprite clips wrong.
  • Per-interior ShadowsOnlyRoof scale - default (14, 1, 14), resize if the interior footprint is larger or low-angle sun leaks.
  • Mobile m_SoftShadowQuality = Medium - if jagged shadow edges are visible on-device, raise to High (2-3x fragment cost).

Out of scope (future work)

  • Cloud / weather shadows beyond the overcast hook (WeatherLightingBridgeLightingDirector.SetOvercast flattens shadow strength under a front; a real scrolling cloud-shadow cookie remains future work).
  • Moonlight shadows at night now come for free where the profile's ShadowStrength curve is > 0 — the single directional light doubles as the moon (see lighting SKILL); tune via the profile, no second light needed.
  • Cross-quad meshes for wide-canopy trees.
  • Normal-bias-by-sun-angle curve.
  • Per-archetype custom _Cutoff tuning beyond ItemSO.castsShadow.

See also

Install via CLI
npx skills add https://github.com/Silac1995/My-World-Isekai-Unity --skill rendering-shadows
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator