Penumbrae get softer with distance, and that is the whole trick
Built on radiance cascades by Alexander Sannikov. Sources for this reference
This is the note behind radiance cascades. It opens with the observation the technique is built on, because the structure only makes sense once that is in front of you, so the first demo below is deliberately the naive method a cascade exists to replace. The cascade's own structure is the second demo.
Real bounced light in a 2D scene is not hard to write. Every pixel asks in every direction whether it can see a light, and averages what comes back. It is about twenty lines and it is beautiful, and the ray count you need makes it unusable.
Six rays gives coarse structured noise, worst in exactly the wide soft penumbrae the technique was for. Sixty-four is much better and is over ten times the cost, and it is still visibly grainy, because stochastic gathering converges as the square root of the sample count: four times the rays for half the noise. Naive gathering has one dial and it is an expensive one.
The observation cascades are built on
Two facts about light in a scene, both obvious separately and load-bearing together:
- A penumbra grows linearly with distance from its occluder. Near a shadow-casting edge the transition is sharp and needs many distinct directions to resolve. Far away it is a wide soft gradient, and a handful of directions describes it completely.
- Radiance from far away varies slowly across space. Two pixels a hundred apart see nearly the same distant light. Two pixels a hundred apart may see completely different nearby light.
So the requirement inverts with distance. Near field: high spatial resolution, low angular resolution. Far field: low spatial resolution, high angular resolution. And crucially the product of the two stays roughly constant, which means a hierarchy of levels each trading one for the other costs about the same at every level.
The structure
Cascade 0 is dense in space and sparse in angle: many probes, each looking a short distance in a few directions. Each higher cascade halves the spatial density, doubles the angular count, and looks further. The intervals are arranged to tile the full range with no overlap, so every ray length is covered exactly once.
cascade 0: probes every 2px, 4 directions, reach 0 to 2px
cascade 1: probes every 4px, 8 directions, reach 2 to 6px
cascade 2: probes every 8px, 16 directions, reach 6 to 14px
cascade 3: probes every 16px, 32 directions, reach 14 to 30px
That is the whole structure in one picture: going right, the probes get sparser and the fans get denser. Every level costs about the same, because the two are trading against each other, and the total lands on the order of the NUMBER OF CASCADES rather than on the order of the radius.
Four times fewer probes and twice the directions per level is half the work per level, and reach doubles each time. So covering a screen-sized radius costs on the order of the first cascade rather than on the order of the radius, which is the entire result.
Then merge downward: each cascade interpolates its parent's result spatially and sums the matching angular intervals. A pixel's final radiance is its cascade 0 probe plus a correctly weighted chain of coarser and further contributions.
What it buys and what it costs
- Noise-free by construction. The directions are fixed and enumerated rather than sampled, so there is nothing to denoise and nothing to accumulate temporally. That is the property that makes it feel different from every other real-time GI approach.
- Cost is roughly independent of light count. Probes gather; they do not iterate lights.
- Ringing at the merge, which is the characteristic artifact. Bilinear interpolation between coarse probes produces visible structure when a probe straddles an occluder. Most of the published tuning is about this.
- Light leaks through thin occluders, because a coarse cascade's ray can step over a wall thinner than its interval.
- It is a real amount of machinery. Several render targets, careful interval arithmetic, and an implementation that is genuinely hard to get exactly right. This is not a twenty line technique.
When it is worth it, and when it is not
Being honest about the threshold, since the machinery is substantial:
- Worth it when the scene has many dynamic emitters, when soft shadows and color bleed are the look, and when the alternative is per-pixel gathering.
- Not worth it for a handful of lights. Three lights with analytic soft shadows from the distance field cost almost nothing and look excellent, and the earlier note on line-integral lighting covers most of that.
- Not worth it if the emitters are static, where a baked light map is better in every way.
- Consider the middle ground first: a low ray count with good temporal accumulation and a decent denoiser is much less code and is what most shipping 2D games do.
The technique is credited to Alexander Sannikov, and the primary source is the paper and the surrounding discussion rather than any implementation. It is worth reading before building, because the interval arithmetic is the part everyone gets wrong first and the part that decides whether it rings.
Rules of thumb
- Penumbra width grows linearly with distance from the occluder. That single fact is the whole justification.
- Near light needs spatial resolution, far light needs angular resolution, never both. Their product is roughly constant.
- Quarter the probes and double the directions each level. Cost per level is then roughly flat.
- Intervals must tile the range exactly. Overlap double-counts, gaps show as dark rings.
- The characteristic artifacts are ringing at the merge and leaks through thin occluders. Budget time for both.
- Under about four lights, analytic soft shadows are better and are a fraction of the code.
One email when something new goes up. No newsletter, no schedule, nothing else.
Double opt-in, so watch for a confirmation email. Unsubscribe any time.