Day 1 - 🔬 Deep dive - Shadow Proxies

Article / 30 April 2026

Shadow LODs were a manual optimization technique for reducing shadow rendering cost. With modern rendering tech like Nanite and Micromesh, they're largely obsolete, but not entirely.

Back in the day

When I just entered the industry I only played around with Visual LODs, which was already challenging enough at times if you had to manually generate them. Any normal, UV or vertex inconsistencies were quite noticeable, and not all studios used automated tools. So for some of the games that I worked on, we manually reduced meshes inside Maya, and then did manual tweaks to polish. Nowadays, we have fancy tools like Simplygon or default to using Nanite-like techniques.

The Old Problem

First, we had offline baking processes that would take care of the heavy lifting. In preparation for that, you needed UVs on your mesh, and then generate a secondary UV set that was a complete unique layout for lightmap generation. Problem: every time an asset changed or if you updated the Time of Day, you had to rebake the level; slow and tedious as you can imagine! The industry responded on two fronts: light probes (storing irradiance as spherical harmonics coefficients) let dynamic objects receive indirect lighting without triggering a full rebake, and the shift to deferred rendering separated the geometry and lighting passes, enabling more dynamic lights without a proportional performance cost.

The more complex and dense assets became, as games increased in scale (more open world games), and the more dynamic worlds have to become, the harder it is to solely rely on the visual LOD also affecting the shadow maps and/or shadow cascades. The shadow depth pass has to evaluate every triangle in a mesh — or worse, every pixel for alpha cutouts, and that cost adds up fast. The solution was a shadow proxy: strip away the visual shader entirely and substitute a separate, ultra-simplified mesh used only for shadow casting, while the full-detail mesh handles visible rendering.

Great example from CryEngine where they demonstrate the reduction from 10k triangles to just 1k triangles. Visually the difference is barely noticeable to the naked eye but performance-wise it will have an impact.

You don't need normal or albedo information in a shadow proxy shader. If you require displacement or alpha-testing for your visual shader, you'll want to integrate those into your shadow proxy shader too, for parity. From an organizational and performance point of view, you want to separate your opaque vs. alpha-tested materials, keeping the number of alpha-tested triangles/pixels to a minimum and not drawing them for the entire mesh if you don't have to.

For visual LODs you can swap out different simplified meshes at predefined draw distance thresholds; the same can be done for shadow proxies. Having a reduced shadow proxy at far distances will also help reduce load on shadow memory. Note: the visual mesh threshold doesn't need to match the shadow proxy threshold. For example, a shadow proxy can draw at a maximum distance of 200 metres while the last visual LOD draws at 500 metres. Shadows at just a few pixels may not be noticeable, but the visual representation still is.

To sum up:

  • Use a custom proxy mesh that only writes to the shadow cascades
  • Assign a dedicated shadow proxy shader; strip any information that isn't needed in this stage of the pipeline
  • Set custom draw distances independent of your visual LOD thresholds

Limitations

The statement "no longer necessary with Nanite" is the right instinct, but it's only fully true for opaque Nanite geometry. Foliage and Characters still remain challenged by custom shadow proxies.
Shadow Physics Asset still useful for Characters. While Foliage needs an alpha-tested fallback option.

How It Worked in Unreal Engine & Proprietary

UE3 / UE4 / Others:

You could assign a simplified static mesh exclusively for shadow casting in a few ways:

  • A dedicated low-poly mesh component with rendering disabled and shadow casting enabled, using a convex hull or box mesh casting the shadow instead of the real geometry
  • For alpha-heavy assets (foliage, fences, chains), this eliminated the expensive per-pixel shadow depth evaluation on alpha cutout materials
  • Per-LOD shadow control: disable shadow casting on lower LODs entirely, or force a simpler shadow representation per LOD level

UE5 / Nanite:

Nanite handles shadow depth passes through its own rasterizer with automatic LOD, which largely removes the need to hand-author shadow proxies for high-poly opaque meshes.

However, Nanite doesn't fully support alpha masked geometry. Alpha-heavy assets still fall back to traditional shadow rendering, which means the proxy technique remains relevant for:

  • Foliage with alpha cutouts
  • Fences, railings, chains, cables
  • Any non-Nanite mesh in a Nanite pipeline

Practical Takeaway

If your project uses Nanite for hero assets, shadow LODs are off your plate for those. But keep the proxy approach in your toolkit for anything with alpha transparency or anything outside the Nanite pipeline. A box mesh shadow proxy on a dense foliage card cluster is still a meaningful win.

© 2026 Stefan Groenewoud — All views are my own, not those of my employer.