Cascade Shadow Map 해상도 상향
ChosenPros
- Same pipeline as before, low implementation cost
Cons
- Increases memory / bandwidth cost, no per-character texel guarantee, affects the whole scene




High-quality character shadows limited to 16 lobby characters — Atlas slot + mask approach delivers readable silhouettes at mobile 1024 resolution.
URP's default cascaded shadow map covers the whole screen with a single map, so each character gets very few texels. We needed a separate shadow region that guarantees a per-character texel budget.
Pros
Cons
Pros
Cons
Pros
Cons
Why Cascade Shadow Map 해상도 상향: In the lobby, characters sit on a single plane, so the benefit of depth comparison is small while acne / bias tuning cost on a 16-bit depth + 256² slot is high. Depth comparison itself was removed; only ceiling / wall influence is blocked by a normalWS.y-based SlopeFade.
The RendererFeature clears the 1024 atlas RT at BeforeRenderingOpaques and renders each caster mesh depth-only into 16 slots. Per caster, the 8 corners of the union bounds are transformed into view space to form a tight orthographic AABB that fits the slot texels snugly. The receiver shader transforms worldPos to slot UV via _CharacterShadowVP[i], and any pixel that is not the clear value is treated as shadow.
diagram: /images/projects/ovensmash/character-shadow-atlas/architecture.svg
diagram caption: Caster → Manager → AtlasPass → Globals → Receiver Shader
A MonoBehaviour attached to the character root. It auto-collects only the child SkinnedMeshRenderers and computes the union bounds. To prevent the bounds from "pumping" frame-to-frame due to bone animation, hysteresis is applied to extents (expand immediately / shrink via lerp); center tracks immediately so movement responsiveness is preserved.
CharacterShadowCaster.GetUnionBounds (Vector3.Max then Vector3.Lerp).A scene singleton registers casters split into Player / NPC, and each frame selects up to 16 — all Players first, then NPCs ordered by camera distance. There's also a recovery path that recollects from the scene when static references are broken after a domain reload.
The previous version estimated the shadow's horizontal drift from the light's tilt and grew the frustum to a square radius. Now the 8 corners of the bounds are transformed into view space and a tight orthographic AABB (xMin/xMax/yMin/yMax) is computed directly, maximizing the texels the character silhouette occupies inside the same 256² slot.
ComputeMatrices and Matrix4x4.Ortho(xMin, xMax, yMin, yMax, near, far).Dropped the conventional depth comparison (coord.z vs stored + bias) and simplified to "a pixel where a caster was drawn into the atlas = shadow." Under reversed Z, clear is 0, so stored > 0 is a hit. The _CharShadowBias parameter is gone, and a normalWS.y-based SlopeFade prevents shadow bleeding onto ceilings / walls.
UNITY_REVERSED_Z-branched hit test in EvalCharacterShadow.


Shadow quality improved at the same texture resolution