Light transport research · RadianceLab
A volumetric caustic through glass, solved in closed form. No neural network, no clamp, no denoiser — and blitzing fast. The sheet is exact; the pair that renders the frame above is consistent, not unbiased, and the number is on this page.
Above: a shaft of light meets a glass sphere and leaves its underside as a waisted horn. That image is the pair: computed on the sheet, gathered by the beam it hands off to. In the equal-pass A/B further down, this caustic's waist is 7.7 px wide where the kernel estimator's is 70 at r = 0.70 and, with the beam at the pair's own radius, 16.1 px.
01 — The problem
Volumetric caustics are the light that has already passed through glass before it scatters in fog. They are among the hardest paths in rendering: the light is focused to a thin, bright sheet, and almost no random path finds it.
The usual answer is photon mapping — fire photons, store them, and gather with a kernel of radius r. That works, but the radius is a lie you agree to: it blurs the caustic and biases the answer, and shrinking it trades the blur for noise. This page is about refusing the lie and keeping the speed.
An analytic estimator avoids the kernel entirely, but buys a new problem. Sweeping a photon into a surface and intersecting the camera ray with it introduces a Jacobian in the denominator — and when the camera ray grazes that surface tangentially, the Jacobian collapses toward zero and the estimator explodes.
A photograph used to sit here, and it was pulled on 2026-09-08. It showed the photon-cone estimator alone on preset 41 at 400 passes and its caption called the bright pixels the tangency locus, at 1189.8× the scene mean. When every film on this site was regenerated from its own producer, that one did not come back: the estimator's own recorded config produces a frame with a twentieth of the shipped film's mean, and on this build the mixture that is supposed to fix it has the higher peak. The frames and the full retraction are kept in section 03 rather than deleted, but they are not evidence for this section's claim, so this section no longer shows them. That the cone is the family's worst primitive is measured elsewhere and stands: worst pixel against the reference, 6291 → 1 once it is mixed — the stat tile at the top of this page.
02 — The idea
A photon arriving at a scattering event still has unused degrees of freedom. Rather than committing them randomly and storing the result, let them sweep.
Fix every dimension of a light path but two, and let those two vary. The scatter point traces out an analytic two-dimensional manifold in space — a sphere, a cone, a disk, a ruled plane. That manifold is a photon primitive, and a camera ray can be intersected with it exactly.
The kernel disappears. In its place is a co-area Jacobian relating the swept parameters to the measure the camera ray actually integrates:
Because the manifold is exact, the estimate is unbiased with no radius parameter at all — the caustic is as sharp as the geometry, not as sharp as your kernel. What remains is the variance problem from section one, and it has an answer that costs nothing but bookkeeping.
03 — The family
Which two dimensions you sweep determines the shape. Twenty-one of them are built, and every one was divided against an independent reference before the next was started — the straight-line members against the next-event oracle to a median of 1.000, the dielectric members against the stochastic beam. The ratios are in the ledger; the one that lands off, the solo hourglass at 0.976, closes to 1.0000 paired. The roster below is the useful part of the space.
Twenty-one is the count that closes the picker: thirty-one slots, less the three baselines that are ordinary sampling, the six kernel estimators, and the one slot that is a rasterised gather rather than an estimator. Earlier versions of this page said nineteen, then twenty-two, and its siblings said twenty; none of those closed against the roster as it is filed today, and the discrepancy is what caused them all to be re-derived. The kernel class used to be two — the tracer beam and the tracer point. Section 04b is where three more arrived, and why they had to. The sixth is the hourglass pair, filed with them on 2026-09-08: analytic on its sheet, it carries the beam's radius everywhere else, and section 05 measures what that radius does to its energy.
| # | Primitive | Swept | Character |
|---|---|---|---|
| 01 | NEE long-ball | θ, φ, t | The oracle. Every primitive is validated against this |
| 03 | UV light quad | u, v | Noisiest toward the light |
| 05 / 06 | UVW cube / ball | u, v, w | No grazing band at all — t² cancels 1/r². Cleanest of the family |
| 07 | Photon sphere | θ, φ | Works with point lights; casts real shadow rays |
| 08 | Photon disk | cos θ, t | Signature artifact: a radial firefly fan |
| 09 | Photon cone | φ, t | Worst single primitive. Also the ior→1 limit of the hourglass |
| 10 / 11 | UT / VT plane | u,t / v,t | Grazing bands perpendicular to one another |
| 12 | MIS · three planes | shared (s,u,v) | 259 → 1. Each member's singular band is where the others are healthy |
| 13 | MIS · direction trio | conditional | 6291 → 1. Sphere + disk + cone under one measure |
| 26 | MIS · planes + trio | shared (s,u,v), six densities | Both regimes in one estimator. Lowest per-pass variance at every emitter size; its masks reproduce 12 and 13 bit for bit |
| 15 | Continuous-φ MIS | closed-form envelope | ∫|a cos φ + b sin φ| dφ = 2√(a²+b²). Grazing band gone |
| 18 | Tracer photon beam | t — 1D kernel | First estimator to show a glass caustic. Ground truth for 20. Also the t column of the lattice |
| 28 | Photon ring | φ — 1D kernel | A circle of radius t sin θ about the axis. Singular where the camera ray is coplanar with it |
| 29 | Photon arc | θ — 1D kernel | A half-circle of radius t about the vertex. Singular along the frame axis, and nowhere the ring is |
| 30 | MIS · ring + arc + beam | arclength on the camera ray | Worst pixel 545.7 → 5.0, lower than the beam's own. Consistent, not unbiased: like every kernel member it blurs, and on top of that its weights do not sum to one at finite radius — so complement mode refuses it as a primary by name |
| 20 | Photon hourglass | φ, r about the axis | The novel one. Kernel-free refractive caustic; solo it reads 0.976, and its guard is a discard, not a clamp. |
| 21 | Hourglass MIS | branch measure | Converged median 1.0000 against the beam at the same radius. The one to use — and consistent, not unbiased: it carries the beam's kernel at weight O(r) on the caustic and at one everywhere else, and its energy moves with that radius, +0.9 % at r = 0.15 |
| 27 | Photon ring-alt | φ, t about the mirror direction | The first glossy vertex. Five free dimensions instead of three — a rough surface imposes no reflection law, so the light point and the polar angle are sampled rather than solved |
The design criterion that mattered: Jacobian flatness first, evaluation cost second, ease of connection third. A primitive that is cheap but singular everywhere is worth less than one that is expensive and well-conditioned — because in a mixture, the singular member is the one that poisons the estimate.
04 — Why a diverse set wins
Each primitive has a grazing locus. The observation that makes the family usable is that they are in different places.
Where one primitive's Jacobian collapses, another's is well-conditioned — and the balance heuristic weights each sample by how well every strategy could have generated it. The member that is about to produce a firefly is precisely the member that assigns itself a low weight. The singularity does not need to be clamped, guarded, or clipped away. It cancels.
Both images are unbiased estimates of the same integral, at the same sample count, and their means agree to four decimals — they are computing the same answer. One of them is usable. That gap is the entire contribution of the mixture, and it costs nothing but bookkeeping: the weights are closed-form.
What this readout used to say, and why it does not say it any more. It read 1189.81 against 13.38, an 88.9× reduction. When renders.py was written and every film on this site was regenerated from its own producer, ten of the eleven came back byte-identical or agreed in energy to 3e‑4 — and this one did not. The shipped fireflies film carried a frame mean of 0.21171 with 63 % of its energy in ten pixels; the film that the recorded config actually produces has a mean of 0.03829 and 1.2 % in its top ten, and at ten times the passes it still does. On this build the two estimators are indistinguishable on this preset, and the trio's peak is higher than the cone's. The numbers above are the two films measured (py docs/tools/filmstats.py stats, peak divided by frame mean); no film has been swapped, and the pair is left standing rather than deleted so that the retraction is where the claim was.
The claim itself is not withdrawn — its illustration is. The direction trio's variance reduction is measured on the roster, not on this frame: worst pixel against the reference, 6291 → 1, the number in the stat tile at the top of this page; and the plane pair two panes up, which regenerates byte-identical, shows the same mechanism at 20.8× on a scene where the grazing band is genuine. What preset 41 needs to illustrate it again is a scene whose tangency tail is real at 400 passes — a scene choice, not a new number, and it has not been made.
The three direction-swept primitives share a conditional-given-p measure, which lets the common selection and area factors cancel before any weight is computed. Without that cancellation the mixture would not be tractable at all.
The two mixtures are built for different regimes. The planes sample a point on the light, so they should improve as the lamp grows; the direction trio conditions on one light point, so it should lose ground as that point wanders. The variance study wrote the crossover down before anything was rendered: the planes overtake the trio once the emitter subtends about 35° at the ball. A second prediction sat beside it for the caustic: the vertex-seeded hourglass (22) overtakes the light-seeded one (20) at 35–41°.
Presets 58–62 are one rig built to settle both: a glass ball in fog under a downward quad whose edge steps 0.2, 0.5, 1.25, 3.2 and 8.0 at constant power — 2° to 77° at the ball — with every cell timed, eight independent pass-batches per cell, and the energy checked against the camera walk at every row. Neither crossover arrived. The trio beats the planes at every size: by 43× on equal time under the smallest lamp, narrowing to about 1.3× at 77°, where the cost slopes carry a 10–30 % timing uncertainty and the equal-time margin is inside it — the per-pass ratio of 2.2× at that row is not. The light-seeded hourglass beats the vertex one at every size, by 236× down to 1.9×. Both trends run the predicted way, so the crossovers exist — beyond the rig, near an emitter edge of 9–10 for the airlight pair and further still for the caustic, where the lamp would be nearly half the width of the fog box. The miss was on the side the study trusted most: the trio's variance floor is 1.10 per pass, not 3.8, and it rises 1.35× over a 1,600× increase in emitter area, not 2×. Both corrections are written into the study beside the predictions they replace.
| Emitter edge | Angle at the ball | 12 · planes | 13 · trio | 26 · both | 22 / 20, caustic |
|---|---|---|---|---|---|
| 0.2 | 2.3° | 114.7 | 2.7 | 3.5 | 236 |
| 0.5 | 5.7° | 41.5 | 3.0 | 3.5 | 111 |
| 1.25 | 14° | 43.4 | 2.2 | 3.7 | 23 |
| 3.2 | 35° — the predicted crossover | 17.3 | 2.9 | 3.4 | 3.8 |
| 8.0 | 77° | 4.7 | 3.6 | 3.0 | 1.9 |
Equal-time cost of one unit of noise for the three airlight estimators; the last column is the vertex hourglass's cost divided by the light-seeded one's. The cost slopes carry 10–30 % error bars (±0.35 on the trio and ±0.2 on the mixture at the last row), so the bottom row's equal-time verdicts are marginal and the per-pass ones are not. The three airlight estimators agree on energy to 0.1 % at every row, and all three read 2–3 % above the camera walk — every bit of that excess sits inside the glass ball's disc, where a swept estimator integrates fog along the unrefracted camera ray and the walk stops at the glass. Outside the disc they agree with the walk to 0.03 %. That is the one camera-leg convention the whole light-sweep family shares, and the camera-leg cap that complement mode switches on closes it.
The third column answers the question the two mixtures invite: why not both? Strategy 26 mixes the three planes with the direction trio under one measure. The obstacle looked like a change of variables — the trio's densities are conditional on a light point, the planes' live on the light's area — and turned out to be bookkeeping: multiplying the trio's densities by the light-point selection density puts all six on the same light-area measure, the area factor cancels exactly, and the six weights are closed-form with no root-find. It has the lowest per-pass variance of the three at every emitter size and, from the third row on, the cleanest tail; it costs 1.2–1.8× the trio per pass because it draws six members rather than three and pays a shadow ray for every crossing that lands, and under the widest lamp it edges ahead on equal time, inside the timing uncertainty. It captures both regimes per sample. Masking its members down to the planes alone or the trio alone reproduces 12 and 13 bit for bit; the check that the shared measure is right is the energy, which agrees with 12 and with 13 to 0.1 % across a 1,600× range of emitter area. Use it when the light size is unknown.
One bug came out of the rig, and it is on the page because the rig is what found it: inside the trio, the sphere and disk members cast no shadow ray while the cone did, so on preset 48 the trio read 1.25× the walk under a glass ball's shadow. Fixed the same day; the trio now reads 1.016, and the mixture inherits the fix.
And the rig's own oracle is the estimator to beat. The reference at every row was the camera walk's single-scatter next-event estimate: a free-flight-sampled scatter point and one shadow ray. Its variance was recorded and never tabulated, and it is lower than any swept member's at every emitter size — 0.35 to 0.67 per pass against the trio's 1.10 to 1.49, and 1.4 to 3.6× better on equal time. That is the honest boundary of this family. Sweeping a dimension of an area light's single scatter does not beat connecting to it; what sweeping buys is the mixture mechanism above, and the connections next-event estimation cannot make at all. Hold on to that sentence — the next section reproduces it exactly, on a different construction, and the section after that is where sweeping stops being optional.
04b — The lattice's other half
A photon leaves a vertex with a direction and a distance: three numbers, (θ, φ, t), in a frame at that vertex. Fix one and sweep two and you get a surface — the cone, the disk, the sphere, kernel-free and shipped since the first week. Fix two and sweep one and you get a curve. There are exactly three of those, and until this week only one of them was built.
The construction is the user's. The ring and the arc, the shared measure that mixes them with the beam, and the observation that closes the lattice are all theirs; what was added here is the transcription into the renderer and the gates below.
Every member of the bottom row is the same integrand times the same kernel 1/(2r), divided by one geometric term: |(∂x/∂u) × d|, where u is whichever coordinate is being swept and d is the camera direction. The tracer beam's familiar 1/sin θ is that expression for a unit-speed sweep. The beam was written first and looked like a special case; it is the t column of a lattice that now closes. The ring (strategy 28) sweeps φ, so its locus is a circle of radius t sin θ about the frame axis; the arc (29) sweeps θ, so its locus is a half-circle of radius t about the vertex itself. Write the volume element as t² dt dμ dφ and the point source's 1/t² cancels it, which is why the ring carries one factor of 1/t that the beam does not, and the arc carries that plus an explicit sine.
Intersecting a camera ray with a circle of tube radius r is ray-versus-torus, which is what these primitives actually are, and the stationary-point condition squares to a quartic. Two things make the shipped solver simpler than the textbook one. The bracket is free and exact — every stationary point lies in [−k−ρ, −k+ρ] — and inside that bracket the quartic's own derivative is a cubic in closed form, whose real roots cut the interval into at most four monotone pieces, each sign change bisected. No companion matrix, no eigenvalues, and no threshold to guess.
The part that is easy to get wrong is that you must sum every stationary point, minima and saddles alike. Two or three roots occur on 57.01 % of hits when the camera ray runs near coplanar with the ring's circle — 51.15 % two-root and 5.86 % three-root over 165,429 measured hits — and those are precisely the configurations the primitive exists for. Keeping only the nearest root would have deleted the geometry the estimator was built to reach, and would have looked like a mild darkening rather than a bug.
In the two-dimensional members the sampling density of the swept coordinate cancels against the emission profile, so the profile is divided out and never evaluated. Sweep one coordinate and it does not cancel, and that single fact sets the whole character of the group. The emission profile has to be evaluated at the crossing — which is why any of these is identically zero at a smooth dielectric (a two-dimensional delta integrated over one dimension is still a delta), and equally why an evaluated payload is exactly what would let a one-dimensional member carry a bounce off a rough surface. A delta in one angle is fine, and the family already ships it: the cone is the polar-delta ring.
A corollary that was run as written on 2026-09-08, and half of it fell. If the emission profile is axisymmetric about the frame axis, the ring's swept coordinate is the symmetry coordinate, and a μ-density shaped like the profile absorbs it entirely — f_e / q is a constant and the profile is never evaluated. That is why the frame axis is the light normal: a Lambertian emitter is axisymmetric about it by construction. Until 2026-09-08 this note cited a cos⁴ lobe reading 1.0087 ± 0.0184 as the verification; that run sampled μ uniformly and evaluated the profile at the crossing — the opposite experiment. Run with the absorbing sampler (run_lobe_absorb.py, μ ~ 5μ⁴, same seed and N) the ring reads 0.987 ± 0.017, 1.018 ± 0.008 and 0.983 ± 0.011 on the broadside, steep and along-axis cameras — unbiased, like the evaluated one — with 1.2×, 2.6× and 2.5× less variance. On the near-tangent camera it has 20× more: the absorbing density rarely visits the μ ≈ 0 rings the profile is dark on and pays them full weight, which is exactly where the ring's tangency family lives. The corollary is right about the profile and wrong about "pays nothing": where the singular family sits in the profile's dark, evaluating is the cheaper deal, and the shipped ring evaluates.
The ring goes singular where the camera ray is coplanar with its circle. The arc goes singular where the ray runs along the frame axis. The beam goes singular nowhere — its parallelism needs two fixed directions to line up by coincidence, while a swept circle hunts the tangency. That disjointness is the argument for mixing them, and it is visible one derivation earlier than any film: at 800,000 samples per cell against a quadrature reference the ring alone reads 2.1323 ± 0.0516 on a near-coplanar camera and unity everywhere else — an excess of 1.13 against a bar of 0.05, 22 sigma, resolved. Only half of that pair is a measurement, and the half that is not is marked. The arc's along-axis cell reads 1.0286 ± 0.0269, an excess of 0.0286 against a bar of 0.0269 — 1.1 sigma, not resolved — and it was bolded here as a measured family on the strength of its centre alone. The arc's tangency family is indicated by this table and demonstrated by its worst-pixel column below, 41.7 times its own frame mean against the beam's 5.9, and by the swarm picture. Nothing downstream leans on the cell: the mixture's case rests on the ring's 545.7 and on the arc's tail, both far outside their noise.
Strategy 30 puts all three on one measure — arclength along the camera ray — and applies the balance heuristic from the section above. Two properties fall out. With one shared kernel radius the 2r cancels identically in the weights, so the shared-width instinct buys the densities for free. And the contribution goes as 1/sin ψ while the weight goes as sin ψ, so the product is bounded and at most one member can be grazing-singular at a time. No member has to hand its tangent in: the three tangents are just the spherical frame rebuilt at the crossing.
Preset 60, 217×140, kernel radius 0.15, converged at 3,200 passes. The oracle is the camera walk's own single-scatter next-event estimate — strategy 2 with min bounce 0 and max bounce 1, the panel's bounce-isolation fields set so that exactly one scatter is accumulated and nothing else can enter the comparison. Its support is the whole frame, 30,380 pixels of 30,380, so every ratio here is a whole-frame ratio.
| cell | ratio to the oracle | median relvar / pass | p90 relvar / pass | ms / pass | relvar × ms | worst pixel |
|---|---|---|---|---|---|---|
| 18 · beam | 1.0208 ± 0.0009 | 108.0 | 210.7 | 1.073 ± 0.062 | 116 ± 7 | 5.9 |
| 28 · ring | 1.1845 ± 0.0234 | 106.4 | 278.1 | 4.159 ± 0.182 | 443 ± 19 | 545.7 |
| 29 · arc | 1.0360 ± 0.0039 | 318.3 | 812.8 | 3.531 ± 0.320 | 1124 ± 102 | 41.7 |
| 30 · mixture | 1.0207 ± 0.0005 | 39.0 | 79.7 | 7.447 ± 0.357 | 290 ± 14 | 5.0 |
Eight disjoint pass-batches of 400, differenced out of the cumulative films; ms/pass is a least-squares slope over a 640 / 1,920 / 3,200 / 4,480 ladder with the film writes discarded, run three times per cell, interleaved, with the run-to-run spread of the three slopes as its bar (4.4–9.1 %). Worst pixel is max over frame mean on the converged film. The last column propagates the cost bar only — a median relvar carries no standard error here — so those bars are floors on the uncertainty rather than the whole of it. Note that SE(ratio) and the relvar columns are different statistics and move in opposite directions as the kernel thins: the frame mean is carried by a heavy tail that shrinks with r. Producers: ra_gate.py var for the ratio, ra_cost.py measure for the cost, ra_equaltime.py for their product and ra_worst.py for the last column — each stores its json beside the others in docs/ring-arc/harness/ra_gate/.
The last column is the whole thesis in one number. The mixture's worst pixel is 109× better than the ring's, 8.3× better than the arc's — and lower than the plain beam's own. The balance weight down-weights each member exactly where that member is about to go singular, and no member is singular where another one is. Per pass it is 2.7× better than the best single member at r = 0.15 and 2.5× at r = 0.05 (39.0 against 106.4; 118.2 against 300.2) — at three draws per pass against that member's one: the ring draws its own (μ, t), the arc its own (φ, t), and the beam sweeps the frame's direction, so a pass of the mixture is three light paths. Per draw, 39.0 × 3 = 117 sits beside the beam's 108.0 — parity — and each draw costs 2.3× the beam's, which is why the equal-time column below, not this one, is the verdict. It is also the only cell whose ratio matches the beam's converged value to four digits with the smallest standard error in the column.
The caveat travels with the estimator. At a finite radius the three members deposit on manifolds a radius apart, so the balance weights do not sum to one pointwise. Strategy 30 is CONSISTENT, NOT UNBIASED. It converges as r → 0 and nowhere else, and it must never be called unbiased. That is also why complement mode refuses it as a primary by name: comp mode's claim is that the two layers together are the whole transport, and a primary that owns a box and then mis-reports its total breaks that claim at every radius the mode is actually run at. Its two members, 28 and 29, are each a single blur-biased estimator of the same box exactly as the beam is, and are not refused.
Since 2026-09-09 the caveat has a mechanism. The kernel half-width is one control for the whole biased family — the Blur width group, shown for every strategy whose class-table kernel bit is set (18, 19, 21, 28, 29, 30) and for the surface map, hidden for the kernel-free rest — and it carries an opt-in progressive shrink, pp.blurShrink = β, under which pass i reads pp.beamRadius·i−β. Within a pass every member of 30 still shares one r, so the 2r cancellation above is untouched; the running mean over passes is then the progressive estimator, and “consistent as r → 0” is something the renderer does rather than something the spec says. Measured on this preset at r0 = 0.30, β = 1/3: the trio’s excess over the beam plateau falls from +0.0036 ± 0.0003 at a fixed radius to inside the protocol’s bar by 6,400 passes, and the ring’s from 0.34 to 0.0125 ± 0.0046, with the derivation’s β* = 1/(2p+d) = 1/3 for the tube consistent with the observed slopes. Default β = 0: every existing film is byte-identical. The numbers and their producer are in docs/ring-arc/SPEC.md §3.1 and docs/tools/blur_shrink.py.
The honest way to read a biased-by-design estimator is as a ladder, so here is the ladder — five kernel radii, 3,200 passes each, every rung carrying its own error bar from its own eight batches rather than one bar transplanted from a neighbour:
| kernel radius | 18 beam | 28 ring | 29 arc | 30 mixture |
|---|---|---|---|---|
| 0.300 | 1.0200 ± 0.0005 | 1.3506 ± 0.0183 | 1.0564 ± 0.0029 | 1.0233 ± 0.0004 |
| 0.150 | 1.0208 ± 0.0009 | 1.1845 ± 0.0234 | 1.0360 ± 0.0039 | 1.0207 ± 0.0005 |
| 0.075 | 1.0200 ± 0.0017 | 1.0902 ± 0.0155 | 1.0245 ± 0.0021 | 1.0197 ± 0.0008 |
| 0.0375 | 1.0179 ± 0.0032 | 1.0556 ± 0.0101 | 1.0238 ± 0.0031 | 1.0199 ± 0.0015 |
| 0.019 | 1.0209 ± 0.0033 | 1.0292 ± 0.0026 | 1.0214 ± 0.0040 | 1.0195 ± 0.0012 |
At r = 0.30, where the ring alone is 33 % high at eighteen sigma, the mixture is 0.33 % high — a hundredfold reduction, both terms measured, neither inferred. And the 0.33 % is itself resolved at 7.5 sigma, which is a change of verdict in the direction that costs us: with a per-rung bar the mixture is measurably biased at the widest kernel. That 7.5 replaces a shipped 5.1, and the correction runs the way that hurts. The 5.1 assumed the mixture and the beam were independent; batch k of every cell is the same block of pass indices, so they are not, and the measured batch correlation there is ρ = +0.57 — the sign the construction predicts, since 30 contains the beam as an MIS member. A positive correlation means quadrature over-states the differential bar, so the shipped label was conservative and the honest one makes the bias more resolved, not less. That is the caveat above showing up as a number instead of a warning, and it is the right number to publish beside the payoff, because the payoff is unharmed. Below r = 0.15 the mixture is indistinguishable from the beam at every rung.
The ring's excess, fitted rather than eyeballed over the four resolved rungs — 0.30, 0.15, 0.075, 0.0375, where the whole-frame excess clears twice its standard error — goes as r1.067 (+0.105 / −0.096, χ² 0.20 on 2 dof) — first order. How far second order lies depends on the yardstick, and the yardstick is now named. The headline is the profile-likelihood statistic — √(30.67 − 0.20) = 5.5 sigma, delta-chi-squared — chosen because it evaluates the fit at p = 2 instead of extrapolating to it. The linear reading, (2 − 1.0670)/0.1055 = 8.8 sigma — from the unrounded fit, which is the convention; dividing the rounded p and sigma gives 8.9, and that difference is arithmetic — is quoted for continuity and is no longer the one to cite: it runs a 68 % Monte-Carlo interval nine of its own widths into a tail it was never fitted on. Neither is a limit of the data — 0 of 20,000 refits reach p ≥ 2.
Why first order rather than second is not settled, and the mechanism this page used to give for it has been withdrawn. The obvious explanation is that a whole-frame average is dominated by the pixels where the ray is near coplanar with the ring's circle, where in general position the numpy model measures 2.4. That explanation needs the near-coplanar band to be the low-exponent region — low is what drags a frame average down to first order — and fitting the band and the rest of the frame separately puts the band's exponent at or above the rest's under both fitting conventions: 1.314 (+0.172 / −0.158) against 1.225 (+0.206 / −0.204) over the rungs resolved within each subset (three of them — 0.30, 0.15, 0.075 — the same rule as the whole-frame fit but on wider bars, so one rung fewer), and 1.571 (+0.121 / −0.105) against 1.322 (+0.155 / −0.144) forced over all five. The mechanism failed its own test, so it is withdrawn rather than softened. What survives is the concentration, and it is measured: the 5 % of pixels with the largest excess carry 64.5 / 63.5 / 60.8 / 58.2 % of the frame's whole excess at the top four rungs, selected on four batches and scored on the other four so that the selection is not the noise being scored. The honest reason the split cannot decide it is that the mask is frozen at the r = 0.30 geometry while the real band narrows with r, so by 0.019 it holds 4.3 % of the excess instead of 60 %. A band that tracks r would be the experiment; it has not been run.
Three labels moved when the bars were measured instead of carried, and all three are recorded: the “unresolved” mark on r = 0.0375 is retracted (1.5 sigma against a transplanted bar, 3.6 against its own); the arc's suspicious non-monotone rung turns out to be 0.20 sigma — it was the bar all along; and the ring's bottom rung, once “exactly on the 2 sigma line”, reads 1.7 sigma once the batch correlation is measured rather than assumed away (ρ is negative for the ring, −0.44 at the top of the ladder, so quadrature was anti-conservative there). Unresolved rather than borderline. The paired ladder reads 17.8 / 6.9 / 4.5 / 3.5 / 1.7 for the ring and 13.8 / 3.7 / 1.6 / 1.4 / 0.1 for the arc, every other verdict unchanged, and the exponent does not move at all — p = 1.0670 on the independence-assuming bars and 1.0673 on the paired ones, 1.067 either way. (Until 2026-09-08 this sentence ended “and the exponent moves by 0.001”. That 0.001 was a grid artefact and not a measurement: ra_fit.py profiled p on a 0.0025-wide grid and reported its node 1.0675 as 1.068, while ra_p2.py used a grid ten times finer. Both scripts now share the fine grid, and harness/ra_gate/p2.json stores the whole derivation.) The caveat travels with it: eight batches give ρ a 68 % width of about ±0.45 and the paired standard error itself is good to about ±27 %, so neither 1.7 nor the 2.0 it replaces should be read to two digits — the point is that the rung is not resolved and that the shipped bar was the wrong estimator, not the wrong digit.
The whole column sits about 2 % above the oracle, and that offset is shared, not a property of the new members: the beam's row is flat in the radius at χ² 1.17 on 4 dof. It was tested on four fronts that could each have killed it. The sharp one is strategy 12, three-plane MIS, which has no kernel at all, finds its emitter by a different route, and renders byte-identically with the photon-lamp convention flag on and off — it cannot even read the flag the sweeps use, and it reads the same 1.0198 ± 0.0007. Change the lamp and both move together, to 1.0336 and 1.0338 on preset 62. The statistic moves 1.4 percentage points across the light-size series, fourteen times its own bar, so it has discriminating power. The offset is a convention residue, it is preset-dependent, and it is not claimed to be zero.
Equal time, same rig: 290 ± 14 for the mixture against 116 ± 7 for the beam alone — a loss of 2.51 ± 0.19×. The mixture beats the two sweeps it contains — 1.52 ± 0.10× the ring, 3.87 ± 0.40× the arc, and a factor of ten on the arc's p90 tail — and it loses to the member that was already there. All three orderings survive their bars, which is why they are quoted with them. That is stated in the ledger and not buried. It is consistent with the family's thesis — these primitives are heavier than plain sampling, and they win on hard paths, not easy ones — but consistent is not confirmed: this group's hard case, a sharp emitter or an occluded lamp, has not been run, and until it is, the 2.51× loss is the whole of the measured verdict.
Single scatter in clear fog with nothing in the way is the easiest transport this renderer has. The beam is the one member of the group that is singular nowhere, it costs 1.073 ± 0.062 ms per pass against the sweeps' 3.5–7.4, and on a rig with no obstruction it is very hard to beat — the same way the camera walk's next-event estimate beats every swept member of the airlight family one section up. What the mixture buys is not speed on that rig. It is that it never has a worst pixel, which is the property that matters the moment the geometry stops being easy: the ring's worst pixel is 545× its own frame mean and the arc's is 42×, while the mixture's is 5.0 — under the beam's own 5.9. A pixel like the ring's is not fixed by more passes. The ring and the arc sit inside the camera walk's own cost class — the walk costs 3.410 ± 0.567 ms per pass here, and they are 1.22× and 1.04× that — while the mixture is 2.2× the walk; the beam is 3.3× cheaper than the cheapest sweep, and the mixture is the only one you can point anywhere. How well is that column known? To about 10 % within a session and about 1.6× between them. It was re-measured on 2026-09-08 as three interleaved ladders on one binary, and the bars above are the spread of those three. The other number that has been quoted for it — a slope over the same eight batches' stored wall clocks, 0.73 / 6.90 / 3.38 / 15.13 — is not a competing measurement and not merely “load-contaminated” in the abstract: three of its four fits want a negative process start (−4.5 s, −5.1 s) where a real one is +0.3 to +0.9 s, two of its ladders are not monotone in the pass count, and at a matched 3,200 passes its renders ran anywhere from 0.61× to 2.05× the speed of tonight's — the machine moved inside the single sequential run that produced it. It does not swap the ring and the arc: that claim was wrong and is withdrawn, and all three measurements order the four members identically. Every ladder point now lives in ra_gate/cost.json.
The frozen batch renders the whole one-dimensional group as geometry rather than as a film: twelve primitives per member, the sample pool frozen, 400 passes. Strategy 28 draws a swarm of nested circles seen edge-on — twelve rings coaxial about the lamp normal, stacking into horizontal arcs of increasing radius, brightest where the sweep is slowest. Strategy 29 draws twelve open hooks, half-circles about the vertex leaning at twelve different azimuths instead of stacking. Strategy 30 draws both of those plus straight streaks: rings, hooks and beams in one frame, and the trio is legible as a trio. No code was needed for any of it — the correlated-batch reconstruct path re-seeds after the camera prefix and calls the ordinary per-pixel sampler, which is strategy-agnostic by construction.
The converged frames make the same argument a second and more useful way. At 3,200 passes the ring's film carries a bright horizontal band of fireflies across the middle of the frame — the locus where the camera ray is coplanar with its circle, exactly where the derivation says it must be. The arc's film carries a bright patch low and centre, on its own axis locus. The mixture's film has neither. The band and the patch are gone and what is left is the smooth fog gradient the beam and the oracle render. That is the disjoint-tangency argument as a photograph instead of a table.
The derivation gate was re-run rather than inherited, at 800,000 samples per cell against a composite Gauss-Legendre reference the estimators share no code with, and then again against an adversarial independent estimator that shares none of the algebra either — no quartic, no root find, no Jacobian, no sin ψ, just a tube indicator integrated by deterministic quadrature. The two rows that gate quotes — A_broadside against the isotropic lobe and against the tilted one — land within 1.2 sigma of unity on all three members. Storing the adversary's whole twelve-row table on 2026-09-08 showed what quoting two rows had hidden: ten of the twelve sit within about 5 % of unity for all three members and two do not. B_steep/lobeT reads 11.65 / 9.99 / 10.22 and C_neartang/lobeA reads 1.58 / 1.49 / 1.72. The disagreement is common to all three members — they agree with each other to about 15 % — which is not the shape of a member's Jacobian being wrong, and it is the only thing this estimator was built to test; both cells are anomalous against the quadrature reference too, and B_steep/lobeT's reference is 4.549e-07, three to four orders below every other cell in the table. That reading is inferred: the settling experiment — shrink the tube, refine the quadrature, watch the two sides converge — has not been run, so those two cells are reported unresolved and the adversary's verdict stands on the other ten, not on all twelve. The 21 pinned films are byte-identical across the change, and the pre-change set was itself verified 21/21 against the last recorded run before a line was written, so the baseline is a measurement and not an assumption. The bias-ladder film and the eight-batch film are 20/20 byte-identical, so the error bars cost no centre.
Two panel behaviours are load-bearing here and worth naming. Every intersection the group makes runs through the estimator's shared options, so a direction-preserving surface is transparent to all three members: a passthrough wall lets the camera stand outside the fog box without any of them noticing, and unlike the three photon walks the group has no walk to relaunch, because it is a single segment from the light. And the group's shadow ray is applied to all three members rather than to the one that happens to need it, which is load-bearing rather than tidy: the supports must agree or the balance weights would be weighting a path class that one member cannot reach.
When a strategy's scene requirement is not met, the refusal is printed under the Strategy combo in orange — what this scene lacks and what would fix it — rather than left in the log, because the symptom of an unmet requirement is a black frame and nobody hovers a control that appears to be working. The one-dimensional group declares that it needs both scene lights and a medium. Complement mode's live ownership read-out sits beside it and prints the resolved partition from the same declaration the runtime uses; it is the read-out whose needs bitmask was corrected on the volume-light rig, where two strategies had declared scene lights while their bodies actually looked for an emissive volume, so preset 43 would have been refused for the wrong reason.
Not in version one, and said so plainly. Single scatter only — all three are the first segment out of the light, which is why the mixture's beam leg is written locally rather than calling the shipped multi-bounce walk. No surface bounce yet, though the evaluated payload above is exactly the property that would allow one. No flexible subset dial: 30 is the fixed trio, and a mask for it would be four lines nobody has needed. And Tr(t) assumes the medium is homogeneous between the vertex and the crossing, which is exact for every fog box these run on. The obvious optimisation — a closed-form quartic solve in place of fifty bisection iterations — was not attempted, because the bisection is the version that is provably right and the cost is not out of range. Which members that covers is a correction. On the re-measured column — three interleaved replicates, harness/ra_gate/cost.json — the ring and the arc are 1.22× and 1.04× the camera walk's own 3.410 ± 0.567 ms per pass, inside its class; the mixture is 2.2× it. Until 2026-09-08 this page put all three inside the walk's class, on a cost column that had no stored artifact behind it.
05 — The contribution
Refraction is where analytic connections stop. A path that bends at two dielectric interfaces has no closed-form connection — which is why caustics have been left to photons and kernels. This one is not.
For a spherical dielectric there is a symmetry that rescues it. Take the axis a = normalize(C − y) from the light through the sphere's centre. The entire refraction chain — entry, interior, exit — is rotationally symmetric about that axis. Rotating the whole chain is a rigid motion, so the exit rays sweep a surface of revolution: a waisted, hourglass-shaped caustic envelope that can be intersected in closed form.
a. The exit rays sweep a waisted surface; the camera ray meets it where the white ring sits, and the two tangents there are a × (x − y) and ω_out.det3 cancels per branch,Two properties make it a result rather than a trick. First, the density p = Σ pc·|J| / |det3| was derived four independent ways and then measured against the sampler, agreeing to 1.0007. Second, as the index of refraction approaches 1 the hourglass degenerates exactly onto the photon cone — strategy 09 — which pins the measure convention against an estimator that was already validated. That limit matches to nine digits.
The pair carries the beam's radius, so it has to be read the way strategy 30 is read one section up: as a ladder. Preset 48's caustic isolated to the pure transmit-transmit class (min bounce 2, max bounce 3), 217×140, eight disjoint batches of 400 passes per cell, and batch k of every cell is the same block of pass indices, so every ratio below carries its batch-paired bar. Producer: docs/hourglass/hg21_ladder.py, artifact hg21_ladder.json, run 2026-09-08. Energy is the currency: a kernel estimator on an open receiver blurs shape and conserves energy, so the energy column is the one to read.
| kernel radius | 18 · beam alone, energy | 21 · pair, energy | 21 / 20 | 21 / 18 at the same r | 21 / its own r = 0.0375 rung | 18 / its own r = 0.0375 rung |
|---|---|---|---|---|---|---|
| 0.30 | 0.03477 ± 0.00004 | 0.03548 ± 0.00002 | 1.0247 ± 0.0004 | 1.0205 ± 0.0009 | 1.0185 ± 0.0004 · 44 σ | 0.9982 ± 0.0022 |
| 0.15 — every frame on this site | 0.03471 ± 0.00006 | 0.03514 ± 0.00002 | 1.0150 ± 0.0005 | 1.0124 ± 0.0015 | 1.0089 ± 0.0004 · 20 σ | 0.9966 ± 0.0022 |
| 0.075 | 0.03472 ± 0.00008 | 0.03495 ± 0.00002 | 1.0092 ± 0.0005 | 1.0064 ± 0.0022 | 1.0032 ± 0.0003 · 12 σ | 0.9969 ± 0.0021 |
| 0.0375 | 0.03483 ± 0.00009 | 0.03483 ± 0.00002 | 1.0060 ± 0.0005 | 1.0001 ± 0.0026 | — | — |
Solo strategy 20 on the same isolation: 0.03463 ± 0.00002, the row every 21 / 20 ratio divides by. Energies are whole-frame mean luminance; ± is the standard error over the eight batches, and the two right-hand columns divide batch by batch. Re-run 2026-09-08 after the hourglass crossing solver went to double precision: the 18 cells are byte-identical, solo 20 rose 0.16 %, and every rung moved by 0.0005 or less.
The beam alone is flat in its radius, as a kernel estimator should be: 0.9982 ± 0.0022 and 0.9966 ± 0.0022 at r = 0.30 and 0.15 against its own r = 0.0375 rung. The pair is not. Its energy rises with the radius it carries, first order in r — +0.9 % at the radius every frame on this site is rendered at, +1.9 % at twice that, both resolved on the paired bar beyond argument. That is the structure complement mode refuses strategy 30 for as a primary: at a finite radius the beam deposits within r of the sheet while the hourglass numerator is evaluated as though the deposit were on it, so the balance weights do not sum to one pointwise, and the total the pair reports for its box moves with r. It vanishes only as r → 0, which is the definition of consistent. Its shape does not move: the energy in its brightest 1 % of pixels is 0.133–0.136 at every rung against the solo hourglass's 0.136, and on the Gate frame its waist is 7.7 px at r = 0.15 and 7.5 at r = 0.05. The kernel shows in the energy, not the width.
What the pair buys is unchanged by this. The solo hourglass reads 0.25 % below the beam on this isolation (0.03463 against 0.03471), and a straight line through the four 21 / 20 rungs meets r = 0 at 1.004 — the guard's discards handed to the beam at weight one. Solo, the hourglass is kernel-free and discards. Paired, it discards nothing and carries a kernel. No shipped estimator of this caustic earns the word unbiased, and this site stopped using it on 2026-09-08.
Because the estimator is parameterised by the refractive index rather than by a stored photon, making it spectral costs one substitution: draw a hero wavelength, evaluate Cauchy's relation, and let the beam and the hourglass share the same channel so the two techniques stay correlated. The caustic separates into a spectrum on its own — a dispersive volumetric caustic, analytic on the sheet and consistent as a pair, for the price of one line.
Three extensions landed after the hourglass itself, and they share a method worth naming before the numbers: each one asks whether some new transport is still a rigid motion of the same swept surface. Where it is, the existing quadric solver is untouched and the extension is exact. Where it is not, the estimator does not approximate — it refuses, by name, in the log.
Two of those rows say more than their numbers. The chain's refusal is the acceptance criterion for the whole approach: a scene the estimator cannot represent exactly renders as a black film and a named log line, not as a plausible picture that is quietly wrong. And the glossy ring's variance row falsified a written prediction — the design note said the ordinary camera walk would overtake the swept estimator as roughness rose, and it does not, at any roughness in range.
What the ring cost, and why it is on this page rather than in a footnote. Sampling the polar angle from a lobe-shaped density pins one coefficient of the shared cone quadric to exactly 1, at which point the leading term cancels in single precision and the estimator invents energy: measured at 81.5×, 108.8× and 8.7× the correct value at roughness 0.05, 0.09 and 0.16. It is the sharpest illustration on this site of why every member is divided against an independent reference before the next is started — the picture at roughness 0.16 looked entirely reasonable while carrying nearly nine times the energy it should have. And the defect was never the ring's alone. Strategies 9, 13, 23, 24 and 26 solve the same quadric, and on 2026-09-07 the shared solver was reformulated — ray-centred, both differences of squares factored, the roots paired — and moved to double for every one of them; 27 keeps the separate double crossing it already had. Five of the twenty-one pinned films moved at 217×140 and 150 passes, and they are exactly the five that reach a cone. The direction was then settled by an arbiter that shares no line with either build, rather than by the fix arguing for itself: the quadric re-derived in exact rationals and cross-checked against mpmath at 120 digits, the two agreeing to 4×10−39, run on the individual samples that moved. Six of the seven films move decisively onto it; the seventh moves by an ulp the other way with its maximum unchanged. The largest single change, −3.80 % on one preset-48 film, is carried by one sample at pixel (83, 52) whose exact crossing lands 0.00275 outside the emitter — no light path, true contribution zero, and the 55.42 the old arithmetic paid it was invented energy. It is not the whole of the −3.80 %, and saying so was sloppy: the film sum moves 1135.22 to 1092.10, a net of −43.12, so that single sample is 128 % of the net and the rest is paid back by pixels that rise — +9.72 at (102, 61) and +2.38 at (90, 56), the two places the Jacobian was too big rather than the root wrong. One number, two mechanisms, and they point opposite ways. One residual is open and is recorded rather than smoothed over: the solver builds its leading coefficient assuming the camera direction is exactly unit length, and on one near-tangency sample the shipped Jacobian is still 1.93× the arbiter's, against the old form's 6.27×.
One boundary is also now measured rather than assumed. A general, non-collinear chain was costed with a standalone harness that links nothing from the renderer and implements the crossing exactly as the specification describes it: 2 475–3 251 ns per footprint pixel, 1.79 roots per pixel, a sheet covering 6.7–9.4 % of the frame. At the batch sizes this estimator runs, that is 188 ms per pass at the theoretical floor and 443–557 as implemented, against one-ball strategy 20's 13.1 — fourteen to forty-two times. The general chain is a no-go, and it is a no-go because somebody wrote the harness rather than because somebody estimated.
The second half of that shot is the point. An estimator that renders nothing, loudly, on a scene it cannot represent is worth more than one that renders something on every scene. It is the same standard as the projection self-check on The camera is not a viewpoint, arrived at independently in a different part of the estimator: refuse rather than approximate, and say which line refused.
05b — The hourglass as a system
The refraction chain through a glass sphere has exactly three free parameters, and a camera ray consumes exactly two of them. That single fact enumerates every analytic hourglass there can be.
Write the chain as y → x₁ → x₂ → x: a light point, an entry point on the sphere, an exit point, a scatter point in fog. Given the emitted direction — polar angle ψ about the axis a = normalize(C − y) and azimuth φ — both refractions are deterministic, and the exit ray is one line. Add the exit distance r and the whole chain is a map (ψ, φ, r) → x. A camera ray is a 1-manifold in R³, so meeting it costs two parameters. Therefore:
The member that ships samples cos ψ uniformly on the cap and sweeps the revolution φ and the exit distance r — "φ is never sampled; the revolution is consumed by the incidence." Its density is p = p_c · |J| / |det3| per branch, and its ior → 1 limit collapses onto the photon cone, which is how the measure was pinned.
What makes the family worth building rather than admiring is the same thing that made the three-plane and direction-trio mixtures work: every row has a different singular locus on the same transport. The revolution form folds at the caustic waist; the meridian form folds along its own half-plane; the exit-distance shell is singular where the camera ray grazes a closed surface; the fixed-apex cone is singular at its own tangency. Under a balance heuristic the member about to misbehave is the member that down-weights itself. And each missing member arrives with its acceptance test already written — its ior → 1 collapse lands on a primitive that is already validated (the meridian sheet onto the disk, the shell onto the photon sphere).
On the word "tridirectional". For the shipped member alone it overclaims: the dielectric vertex is derived from the light-side sample by Snell's law, not seeded, so the honest count is two subpaths joined at a derived vertex. It becomes literally accurate for the surface-seeded member — sample a coordinate of the entry point on the sphere and hang the light connection and the swept exit off it: three independently parameterised pieces — light, the two-segment dielectric chain, sensor — joined at two constraints. Used for the family, and defined on first use, it is a definition rather than a misuse.
05c — The other hourglass
The shipped hourglass keeps its free angle on the light side and derives the entry point. Turn that around — sample the entry point on the glass and an incoming angle about its normal — and you get a simpler object with a different reach.
Sample x₁ on the ball and a polar angle θ_in about the normal n(x₁). Snell fixes θ_out; incident and refracted rays share one azimuth. Revolving that azimuth sweeps two cones apex-to-apex at x₁. For a sphere the normal passes through the centre, so the revolution is a symmetry of the ball and the whole chain — entry, chord, exit — rotates rigidly. The exit rays sweep a surface of revolution about C–x₁, and the camera ray meets it by the same revolved-quadric solve the first hourglass already uses.
x₁ (red), its incident cone opening into air, the chord and exit family revolved about the axis through C, and the camera ray meeting the exit sheet in fog. At the crossing azimuth the incident ray is one ray — so it is traced back, and here it hits the emissive quad.That last clause is the whole story of when this member applies. Count dimensions: x₁ (2) + θ_in (1) = 3 sampled, and the camera ray consumes the two swept ones. Nothing is left for the light side. With an area emitter the incident ray simply hits it; with fog before the glass it becomes a beam to connect along — a double-scatter caustic nothing renders analytically today. With a point light a single ray cannot hit, and the classic single-scatter caustic has no analytic vertex-seeded member at all. That class belongs to the light-seeded hourglass — which is exactly what its axis-revolution trick buys. The two are complementary, and the availability matrix by surface type and medium per side is written out in docs/hourglass/VERTEX-HOURGLASS.md.
The member above is not quite the sketch it came from. Seeded at the entry, it lets the camera meet the exit family only after a second refraction — so the sheet is a hyperboloid whose waist sits out in the fog, not at any vertex. The sketch had the waist at the sampled vertex, and that is a cleaner object: given θ_in, the interface law fixes θ_out and the two directions share an azimuth, so the admissible pairs are exactly two cones apex-to-apex at the vertex — same side and same angle for reflection, opposite sides and different angles for refraction. The camera meets the outgoing cone itself, and a cone's intersection and Jacobian are strategy 9's, verbatim, with the apex moved onto the glass.
What the two cone members measured. Both converge to 20's energy — 23/20 reads 1.000 once its tail has settled (48k passes against 20's converged 12k) and inherits 20's ~1% residual against the beam to four digits — but standalone, the exit cone is not the more efficient member: at equal passes it lights 50–60% as many pixels as 20 with the heaviest tail of the three (its worst pixel 20× 20's), and its own 12k/48k ratio is 0.985. The reflection cone is the real gain: it is the first analytic member of the L Srefl V E class, matches the beam's reflection branch at 0.998 on a single glass ball, and fills 1.5× the beam's pixels. The variance study says why — the vertex members are light-trace-limited, and the exit cone also pays a chord back through the glass. Its remaining case is the {20, 22a, 23} mixture: three members with different singular loci (waist fold, sheet tangency, cone tangency), untested until the shared-measure ledger lands.
This is the member that earns the word "tridirectional". Light subpath, sensor subpath, and the two-segment dielectric chain seeded independently and joined at two constraints. Used for the family, defined on first use, it is a definition rather than a claim about connection edges.
05c — Surfaces
Every primitive above was certified by one number: its median ratio against an independent estimator of the same integral, converging to 1.000. Surfaces had no such estimator to divide by. So the first surface code in the integrator is not an estimator — it is the thing estimators will be divided against.
At an opaque, non-emissive hit in the camera walk, make one Lambertian light connection using exactly the light set and sampling densities the medium estimators use, and stop. No continuation bounce. Mirrors and glass are untouched; the walk still terminates where it did. It is a reference, deliberately, and it is switched off by default so that every previously validated number remains bit-for-bit reproducible.
f = ρ/π · cos_s · L_e · cos_y / r², with the emitter's own directional profile and the transmittance through any fog on the connection.The comparison needed a small piece of plumbing that did not exist: a headless control for the environment light. The test scene is an open-fronted Cornell box, and sky light reaching its walls is a path class the integrator has no emitter for — so it had to be zero on both sides, or the ratio would have measured the sky rather than the estimator.
The obvious surface primitive — intersect the swept photon sheet with a wall, get a footprint, evaluate where the camera ray lands — cannot be an estimator. Count dimensions: three unknowns, four equations. A 2-manifold sheet meets a 2-manifold receiver in a curve, and the camera's hit point is almost surely not on it. That missing dimension is exactly what a photon-map radius has always been buying.
|N·d|.The repair is symmetric: give the camera a sheet as well. Two curves in a 2-manifold meet in isolated points, and the Jacobian is det[N_p, N_c, n_S]. Both incidence cosines land in the numerator, so grazing drives the weight to zero rather than infinity — the opposite of the medium primitives' failure mode. It also has a closed-form density in both directions, which is the admission ticket to the MIS network. That is the next estimator; the reference above is what it will be divided by.
05d — When does an estimator work well
"Planes work when they face you" is true and useless. The systematic version is a closed-form Monte Carlo of every primitive's weight over the crossings a camera actually sees — 22 estimators, four parameter families, every number cited to a run.
Each analytic primitive samples some photon dimensions with a density p, sweeps two more into a sheet, and meets the camera ray at a crossing with weight
P, the zero point-mass alone contributes (1 − P)/P. Measured as the whole story for the UV quad (rel std = 1.05–1.16 × √(1/P − 1) on 90% of pixels) and as the exponential wall of the photon sphere in dense fog.W ~ ε^{−1/2}, tail index 2, and E[W²] is log-divergent. The sample variance of a fold member never converges (the sphere's grows 5.2 → 20.1 from 10³ to 1.6·10⁷ samples) and must never be read as a convergence gauge. A Cauchy fan (the disk): bounded, but silent on two exact rays.g = 0.8 divides the sphere's variance by 23 and multiplies the disk's by 11 on identical Jacobian histograms.g helps one member and hurts the other.The efficiency question between the two seeds has an answer, and it is not the Jacobian. The vertex members are light-trace-limited: at the baseline waist their light half succeeds on 1–2% of roots, and that is the whole 30–90× gap in coverage below. Their Jacobian term is actually 2–3× smaller than 20's, with no axial pathology.
| member | coverage | cv² | relvar | wins when |
|---|---|---|---|---|
| 20 light-seeded | 0.738 | 8.2 | 11 | point lights and emitters under ~10° — nothing else exists there; worst at the paraxial focus (331), best just under the ball (4.2) |
| 22a entry-seeded | 0.011 | 2.5 | 331 | emitters over ~35°: overtakes 20 at edge 2.4 (27.6 vs 65); flat in ior |
| 23 exit cone | 0.004 | 2.5 | 978 | only low ior (≤ 1.2) with rays perpendicular to the axis; its back-trace through the ball loses coverage as ior rises |
| 24 reflection cone | 0.003–0.006 | 1.7–10 | 450–2140 | reflection caustics from emitters of edge ≥ ~1 — 1.3–50× the reflected beam; loses below edge 0.3 |
| 18 beam, r = 0.01 | 0.110 | 0.14 | 9.3 | as good as 20 at the waist; degrades linearly with the bundle radius; kernel-biased at the axial caustic |
What the numbers say to do next. Not MIS between the seeds — their densities live in different measures and the vertex members rarely have a root where 20 does. Importance-sample the light half instead: aim θ at the emitter and the 1–2% success rate is the entire gap. The medium, meanwhile, is irrelevant to the whole hourglass family (coverage 0.738 at every σt).
ρ → 0 at once.Six of the fifteen rules, each with its measurement in docs/variance/README.md: a single swept plane degrades like sin(γ)^{−3} in its angle to the camera; the three-plane mixture caps the worst pixel at 1.5 rel std in every viewing direction; never use the random-orientation plane when the continuous mixture exists (same samples, 1.6–2.2× better); the cone has an exact on/off criterion for bounded variance; the medium density matters only to members that sample a distance from it; and epsilon guards are irrelevant to variance — acceptance geometry and mixtures are what keep it finite.
The study also records where its own Monte Carlo means did not match quadrature — a −0.7% cone clamp bias, the beam's kernel bias at the axial caustic, and a fold-tailed running mean sitting 31% high at 4·10⁵ samples before settling — so nobody has to rediscover them.
06 — What the estimator actually looks like
Every estimator on this page samples a fresh primitive per camera sample, so the geometry averages away before you can see it. Reuse one batch across the whole frame instead and the individual swept sheets stay on screen — each weighted by its own co-area Jacobian, which is exactly the quantity the rest of this page is about.
This is photon mapping's trick applied to analytic primitives, and it cost one line. The integrator already drew every photon-side random number after the camera ray was built, so correlating is a split of the random-number stream rather than a refactor: seed the photon side from the primitive index instead of the pixel, and every pixel that lands on index k rebuilds the same primitive bit for bit. Not one strategy block changed.
The variance study classifies how each primitive's Jacobian vanishes — constant across a pixel, linearly, as a square-root fold, or as a bounded fan. That classification turns out to be literally a prediction about what the frozen batch looks like, because the Jacobian sits in the denominator.
The balance heuristic changes a weight formula and draws no random numbers. So the two frames below are the same frozen batch, the same sixteen primitives in the same places, with only the edge weights different. Nothing about the geometry moved.
The design document predicted a picture for each family before any of them was rendered. Most were right. Two were not, and they are worth more than the ones that were.
The trap, fired deliberately. The normalisation is one over the number of primitives drawn, never the number that crossed the ray. The wrong version was implemented behind a debug flag first, purely to watch it fail: it reads 2.1× to 6.8× too bright here, and it converges — 4.385, 4.447, 4.451 at rising pass counts on one preset. A quietly wrong image that looks more correct the longer you render it is the worst failure mode available, so it is now a thing this project has seen rather than a thing it was warned about.
06b — The speed
Those three do not usually share a sentence about a volumetric caustic. Neural methods buy speed with a network; kernel methods buy it with blur; exact methods have been slow. The hourglass solves its sheet in closed form at the speed below. The word it does not get is unbiased: solo, its guard discards; paired, it carries the beam's kernel at weight O(r), and section 05's ladder says what that costs. The numbers below are what make the rest of the sentence true.
The first row is worth a sentence, because it is the kind of number this project publishes rather than hides. Eighty-eight percent of a photon-primitive pass was the renderer waiting for a vertical blank: the window hardcoded a swap interval of one and drew one accumulation pass per frame, so every pass paid a display refresh against 0.76 ms of actual work. It was found by one measurement — a twenty-fold change in film size moved the per-pass cost by seven percent, so nothing inside the pass could own it — and fixed with a passes-per-frame budget. Thirty-three films, byte-identical before and after. The estimator had been fast all along; the display was hiding it. How reproducible is a millisecond on this site? Measured, and only once: the one cost column that has been run three times, interleaved, on a single binary holds to 4.4–9.1 % within a session, and moved by about 1.6× between two sessions a day apart on this laptop (docs/ring-arc/harness/ra_gate/cost.json). Every wall-clock number on this site carries that precision, this one included. The ratios it is spent on — 7.05 against 1.17, 16.7× on the rasterised gather — are taken inside one session, which is the half of it that reproduces.
The frame at the top of this page is the measurement. The Gate, preset 54, 363×505, strategy 21, 16,000 passes. Shot as a pixel-registered A/B at 6,000 passes against the stochastic beam at r = 0.70: the analytic side's waist peaks 5.3× higher and its full width at half maximum is 7.7 px against 70, while the two frames agree on total energy to 4 %. Same transport, nine times sharper, at the same pass count — against a beam given nearly five times the pair's radius. A 1D kernel's width scales with its radius, so on 2026-09-08 the same frame was rendered with the beam at the pair's own radius, 16.1 px across the waist (14.1–18.2 over the band): at matched radius the pair's waist is the tighter by a factor of 2.0, and the remaining 4.5 was the competitor's knob. The pair at a third of its radius, r = 0.05, stays at 7.5 px, so the waist is the sheet's and not the kernel's; its energy is where the kernel shows, and section 05 has that ladder. Both extra films are measured by the same producer over the same band and stored beside the four numbers below. Two of those four numbers are a correction. The readout published 4.4× and 57 px until 2026-09-08; those came from a hand reading whose row was never recorded, and the films measure neither at any row. docs/tools/waist.py is now the producer: it takes the peak and the full width at half maximum of every row in the seventeen-row waist band of the same two films this page inlines, and reports the band median with its row-to-row spread — peak ratio 5.3× (4.7–6.2 across the band), width 70 px (68.5–73.1) against 7.7 px (6.1–10.4), energy ratio 0.96003. The wall-clock of that frame is the one number this section does not yet print: it is what the recording below is for, and it goes in the caption the day it is shot.
The idea of sweeping a photon's unused dimensions into an analytic manifold is not mine, and it is earlier: Bitterli and Jarosz's photon planes (2017) and Deng et al.'s photon surfaces (2019) proved the variance argument. They proved it at offline cost. The planes paper ran on sixteen Xeon threads, compared estimators at ten minutes each, and reports absolute times of hundreds to thousands of seconds per image, for a 2.4–40× variance reduction over photon beams. The surfaces paper publishes no wall-clock and no hardware at all; its results are equal-time variance ratios, and it shows individual spinning estimators with variance up to 1.8 million times path tracing before MIS tames them. It also names, in its own limitations, the regime it lacks a robust solution for: a medium interaction immediately after a surface event.
This project does not implement either paper's primitive. Its swept planes are a different split of the same dimension count, and the published multi-scatter construction is structurally inexpressible in the class table this family is built on — the transport page says exactly where. What it shares with that work is the idea. What it adds is an implementation fast enough to show what the idea is worth: 1.17 ms a pass on a laptop's CPU cores with no GPU compute in the loop, a rasterized gather that is byte-identical to tracing, a MIS network whose weights are closed-form with no root-find, and a dielectric member — the hourglass — that lands the specular case of the regime the surfaces paper left open, and, paired with the beam, converging to 1.0000 against the beam at the same radius — consistent, with its radius-dependence measured at +0.9 %. No speed ratio against the published work is printed here, because the scenes, resolutions and hardware differ; the comparison that is fair is the one above, against the kernel estimator in the same renderer, and it is 9× in width at equal passes against the beam at r = 0.70 and a factor of 2.0 at the pair's own radius.
06 — How it was proven
Every primitive in the family had to divide against something it shares no code with, and land on 1.000. Every row that claims it has the run behind it; the ones that land elsewhere — the solo hourglass at 0.976, the beam at 1.048, the reflection cone at 0.998 — say so in the ledger, and the pair closes the first to 1.0000.
The habit that mattered most was negative. Reasoning about why an image is dark does not work. One investigation ran for several rounds on careful inference, reached a confident wrong conclusion, and recorded it in a commit message as settled. A single counter in the actual code overturned it in one run: 27657 rays, 15131 hits, 63% correctly blocked. The bug was elsewhere. Instrument first.
07 — What it does not do
The scope is stated as precisely as the results, because a boundary you can name is what makes a result usable. These six are the boundary, and the first one is the thesis of the whole family.