P
Photizon
AcademyContact

Documentation

Illumination Analyzer

Operating reference for the non-sequential ray tracer: what the engine does, what every output means, where every pinned number came from, and what the model does not claim.

Open the Illumination AnalyzerLast updated 17 August 2026

1. What this tool is

The Illumination Analyzer is a non-sequential Monte-Carlo ray tracer that runs entirely in your browser. You build a scene from optical elements — planes, spheres with ports, concentrators, tubes, lenses — attach detectors, and trace rays from a source through every reflection, refraction and scatter event until the power is absorbed, escapes, or is accounted for by the run’s own bookkeeping. The outputs are radiometric: irradiance maps in W/m², far-field intensity in W/sr, and a power ledger in watts that closes to numerical precision on every run.

“Non-sequential” is the load-bearing word. In the Ray-Optics Designer, light visits surfaces in the order you list them — that is what lens design needs. Here, a ray visits whatever the geometry puts in its way, as many times as the physics demands: the fifth bounce inside an integrating sphere, the double-reflection ghost inside a window, the skew path down a lightpipe. That is the regime of illumination engineering and stray-light analysis, and it needs a different engine, different statistics, and a different kind of honesty about uncertainty. This page documents all three.

The scope fence, stated on both sides. Rays here carry power, not phase: this is incoherent radiometry. Interference, diffraction and guided modes are real physics that this tool deliberately does not model — they belong to the wave tools (the thin-film simulator, the grating tool, the mode solvers). If your two beams are mutually coherent, your features are wavelength-scale, or your “tube” is a few microns wide, the ray answer is the wrong answer, and no Monte-Carlo error bar will warn you. The converse also holds: for a 2-meter room, a baffle stack or a condenser, wave optics is intractable and ray radiometry is the correct tool.

2. How the engine works

Each run launches rays in batches from the source. A ray carries a position, a direction, and a power weight w (watts). At every surface hit the surface property decides what happens: absorption (the weight is tallied and the ray ends), mirror or Lambertian reflection, Fresnel refraction (the ray splits deterministically into a reflected and a transmitted child — see §9), or scatter. Rays that hit nothing escape and are binned into the far-field histogram. Everything is computed in double precision, and every intersection is exact: the P1 geometry is built from analytic primitives (no meshes), so a sphere is a sphere to machine precision, which is what lets the energy ledger close to ~1e-13 instead of ~1e-4.

Determinism. The random number generator is Philox4x32-10, a counter-based RNG whose reference vectors are published and which the test suite validates bit-for-bit. Every random draw is keyed by which ray, which bounce and which decision it feeds, so a run with a given seed is exactly reproducible — not “statistically similar”, identical to the last bit. This is why a share link reproduces the run it was taken from (§11), and why the engine can be regression-tested exactly.

What the engine does NOT do at P1: volume (bulk) absorption inside glass — a ray crossing a lens loses power only at the Fresnel surfaces (this activates at P2 with proper media); wavelength dependence — the trace is monochromatic-equivalent, one set of optical constants per run; importance sampling toward detectors — estimates are unbiased analog Monte Carlo with the splitting and roulette rules of §9, nothing else redistributes samples.

3. Quantities and units

Everything is radiometric, in SI units:

DisplayedUnitDefinition
Map bins (Irradiance view)W/m²bin power ÷ exact bin area
Far fieldW/srbin power ÷ exact bin solid angle
Ledger rows, detector totalsWsummed ray weights

The divisions use exact areas, never approximations: a 32×32 map on a 2 m × 2 m target divides by exactly (2/32)·(2/32) m², and the far-field bins are constructed equal-solid-angle (uniform in cos θ and φ), so every bin subtends exactly ΔΩ = (2/n_μ)(2π/n_φ) steradians. With the default 40×32 binning that is ΔΩ = 9.817e-3 sr.

Outputs stay in the radiometric units above for now. Eye-response weighting (the CIE V(λ) function) ships once its data licensing clears; every eye-weighted quantity is a weighted version of what the tool already computes, so nothing about the physics changes when it arrives.

4. Error bars, and how to read them

A Monte-Carlo result is an estimate, and an estimate without an uncertainty is not a measurement. This tool treats that as a design rule rather than a footnote.

Where σ̂ comes from. The run is organized in batches. Every displayed quantity — each map bin, each ledger row, each detector total — is the mean over batches, and its standard error σ̂ comes from the scatter between batches. This is the batch-means estimator; it is itself validated in the test suite by a coverage test (over many independent seeds, the true analytic value falls inside ±2σ̂ about 95% of the time — measured 0.950).

The convergence target. The run continues until the median relative σ̂ over the lit bins of your map reaches the target (default 5%, adjustable 1–20%), or the ~60 s cap stops it — in which case the achieved σ is displayed instead of pretending the target was met. Refinement never restarts: asking for a tighter σ adds batches to the same deterministic stream, so everything you already computed still counts.

Hatched bins. A bin that has collected fewer than N_min = 10 rays renders hatched, not colored. With so few samples its σ̂ is itself unreliable, and coloring it would present noise with the same visual authority as a converged value. Hatching is a display rule only — the underlying tally is unbiased and keeps accumulating; the bin turns on when it earns it.

The lit-bin caveat. The convergence metric is measured over the bins that are lit, and the lit set grows during a run as dim bins cross N_min. Early in a run on a scene with a large dim area (a wide floor under a narrow beam, say), “target reached” can fire while much of the map is still hatched. The map footer always states the lit fraction — “N% of bins carry at least 10 rays” — and warns when it is below 50%. If you care about the dim regions specifically, lower the target σ or simply let the run continue; the hatched bins fill in with more samples.

No smoothing. The maps are never smoothed, interpolated or denoised. A smoothed Monte-Carlo map looks converged at any sample count, which is exactly the lie this tool is built not to tell. What you see is the estimator, bin by bin, with its honest noise.

5. The energy ledger

The Energy ledger view is the run’s conservation statement. Every watt the source emits ends in exactly one of these rows:

  • Absorbed, per element — weight tallied at absorbing surfaces and at lossy reflectors (a ρ = 0.9 wall absorbs 10% of each arrival).
  • Escaped — rays that left the scene (these also feed the far-field histogram; the two agree to 1e-12 by an engine invariant).
  • Roulette balance — the Russian-roulette rule of §9 kills some low-weight rays and boosts the survivors; both sides are ledgered so the expectation is exactly preserved.
  • Depth-capped — weight still alive when a ray hits the generation cap. It is reported, never silently dropped. If this row is more than a rounding artifact, raise the cap (§9).

The closure residual — emitted minus the sum of everything above — is displayed and is typically at the 1e-13 level: floating-point summation error, nothing physical. A ledger that closes does not prove the physics is right (a biased scatter model conserves energy too — the statistical gates in the test suite exist for that), but a ledger that fails to close proves something is wrong. It is the cheapest, strongest invariant a transport code has, and it runs on every batch of every run you do.

6. Elements and geometry

A P1 scene is built from seven element kinds, each carrying exactly one optical property:

ElementGeometryTypical use
Rectangleflat rect, half-width × half-heighttargets, walls, apertures
Diskflat disk, radiuscatchers, stops
Sphere with portfull sphere, optional circular port by area fractionintegrating spheres
CPCcompound parabolic concentrator wall, exit radius a′ + acceptance θₐnonimaging collection
Baffled square tubesquare section, length, 0–N interior baffles with clear aperturesstray-light control, lightpipes
Plano-convex lensspherical cap + plane, derived exactlycondensers
Biconvex solidintersection of two spheres (CSG)thick-lens transport

Orientation is exact by construction. Elements point along one of the six coordinate axes, with an optional tilt. This is deliberate: the six axis vectors are exact (0, ±1), whereas a general rotation matrix built from angles carries rounding (sin 180° = 1.22e-16, not 0), and the engine’s verification fixtures demand bit-exactness. The tilt path is only engaged when the tilt is nonzero.

One property per element. A “room” is not one element with six materials — it is six rectangles, each with its own reflectance. This keeps every element’s physics readable at a glance and matches how the energy ledger reports absorption (per element).

The port fraction. The integrating-sphere port is specified as the fraction f of sphere area removed, not as a half-angle, because f is the quantity the sphere-multiplier theory is written in (§10) and because the conversion cos θ_port = 1 − 2f is exact in that direction. A 5% port is exactly cos θ_port = 0.9.

Why no cylinder at P1. The P1 solid set is ruled: analytic surfaces whose intersections the engine computes exactly, with the full sphere as the only CSG leaf. A round tube is a P2 element; the baffled tube is square-section, which for baffle logic is the same physics (successive apertures clipping the skew-ray population) with exactly computable geometry today.

7. Sources

Five source kinds, all specified by total flux Φ in watts:

  • Isotropic point — uniform over 4π sr. Intensity I = Φ/4π.
  • Cosine point — Lambertian-lobed point source, I(θ) = I₀ cos θ with Φ = π I₀. The classic model for a small flat emitter.
  • Lambertian disk — area source of radius r, radiance L uniform; Φ = πL·πr².
  • Lambertian sphere — spherical shell emitter; Φ = πL·4πr².
  • Collimated disk — a beam: parallel rays over a disk, Φ spread uniformly by area.

The flux conventions matter more than they look: they are what the analytic benchmarks in §10 are exact against, and they are what makes results comparable across sources (“the same 1 W through a different emitter”).

8. Detectors

Any absorbing element can carry a detector: a total-power bucket (W), a power-per-generation ladder (the bucket split by how many surface interactions each arrival had — this is what resolves a ghost sequence, §9), or an irradiance map (nx × ny bins over the element, W/m²).

Detectors are one-sided, and this is physics, not convention. An irradiance detector tallies only rays arriving against its normal — the side it faces. During verification this rule was found the expensive way: a detector inside a ρ = 0.9 integrating sphere that accepted back-side hits read +19% high, because the back of the patch sees the brightly lit far wall. The transport was unbiased; the measurement was wrong, and two independent reference tracers agreed against it. The practical consequence: a detector facing away from the light reads exactly zero. The tool checks for this (a preset-level gate plus a runtime advisory when a detector records nothing while the ledger shows power arriving), but when you build your own scene, check the detector axis first.

Map bins carry two numbers per bin: the power-weighted irradiance estimate, and the count of rays that contributed. The count drives the N_min = 10 hatching rule of §4 — it has to be a true ray count, because with ray splitting and roulette a bin’s power alone cannot tell you how many independent arrivals produced it. The count is never used as a variance formula denominator; σ̂ always comes from batch statistics.

Detectors attach to absorbing surfaces only. A detector on a mirror would be a measurement that perturbs nothing and means nothing; the scene builder refuses it rather than silently ignoring it.

9. Ghost paths, splitting, and roulette

At a Fresnel surface the ray does not randomly choose reflection or transmission — it splits deterministically into both children, each carrying its exact Fresnel share of the weight. Splitting is what makes ghost analysis work: every specular sequence exists in every run, at exactly its analytic power, rather than being an event you hope the sampler visits.

The ghost ladder, exactly. Send a collimated beam through a plane glass plate (n = 1.5, so each surface reflects R = 0.04 exactly at normal incidence, T = 0.96). The emerging families are geometric in R:

OrderPathPower (Φ = 1)
direct transmission0.9216
first transmitted ghostT²R²1.47456e-3
second transmitted ghostT²R⁴2.3593e-6
first reflectionR0.04
second reflected ghostT²R0.036864
third reflected ghostT²R³5.8982e-5

The first ghost-to-direct ratio is R² = 1.6e-3 — the number every stray-light course starts from. The engine’s acceptance suite pins all six orders to a relative error below 1e-12, and the Ghost ladder preset (§10) shows them in the per-generation detector view, live.

Splitting needs a brake. Every split doubles the ray count; an enclosure with reflective walls would grow paths forever. Two mechanisms bound the run, both ledgered:

  • Generation cap (default 32): a ray ending here has its remaining weight reported in the ledger’s depth-capped row — visible, never vanished. For a high-multiplier integrating sphere the cap must be large (the preset uses 4000) because power genuinely survives hundreds of bounces.
  • Russian roulette (optional weight floor): below a chosen weight, a ray survives with probability ½ at twice the weight — an unbiased trade of variance for time. Both the killed weight and the boost are ledger rows, so the expectation is preserved and the trade is visible.

10. The presets, and the numbers they pin

Every preset is one of the engine’s own verification fixtures — geometry and optical values are spec-printed test scenes with known answers, not illustrations. Nothing in this table was hand-tuned to look good; each row states the analytic anchor the scene is gated against.

PresetThe anchor
Cosine-fourth falloffE(θ) = (Φ/π h²) cos⁴θ for a cosine point source over a plane. At Φ = 1 W, h = 1 m: center 0.3183 W/m²; the corner of the 2 m target sits at cos θ = 1/√3, exactly 1/9 of the center
Lambertian sphere over a planeE = πL R² h/r³ from an extended spherical source; on-axis at R = 0.2 m, d = 1 m: πL(R/d)² = 0.1257 W/m²
Integrating sphere with a portthe sphere-multiplier family (Goebel 1967): with wall ρ = 0.9 and port fraction f = 0.05, total wall irradiation = Φ(1−f)/(1−ρ(1−f)) = 6.552Φ, wall absorption 0.6552Φ, escape 0.3448Φ — a closed geometric series the run reproduces within its stated σ̂
Ghost ladder — plane platethe §9 table, six orders exact in R-products
CPC concentratora′ = 25 mm, θₐ = 20° ⇒ entrance a = a′/sin θₐ = 73.10 mm, length (a+a′)/tan θₐ = 269.5 mm, geometric concentration 1/sin²θₐ = 8.549 — all derived, not typed. The angular cutoff at θₐ is the defining CPC property (Winston, Miñano, Benítez ch. 4): the engine’s measured 3D transmission falls from 0.865 at 19° to 0.135 at 21°
Box room2 m cube, ρ = 0.6 walls, downlight: the interreflection class of the standard room-photometry test cases; the floor map’s direct-plus-reflected structure
Plano-convex condenserthe exact refraction chain through a derived spherical cap — the fixture behind the engine’s lens-transport gate
Baffled tubethree absorbing baffles in front of a detector — successive apertures clipping the stray population; also the worked example of the detector-sidedness rule (§8)
Square lightpipethe same square-section element, mirror walls: a Lambertian disk homogenized over 400 mm, uniformity read directly off the exit map

12. How this engine is verified

Summarized because it is the reason to trust the numbers above; the complete gate-by-gate record is part of the engineering record behind the tool.

  • Exact gates: energy-ledger closure on every scene (~1e-13); solid-angle fractions, view-factor reciprocity, étendue invariance through a lens (1e-13 on the per-ray skew invariant); the six-order ghost ladder below 1e-12; CPC geometry derived vs constructed at machine precision.
  • Statistical gates: every analytic irradiance law in §10 as a z-gate against the run’s own σ̂; sampling distributions by χ²; the −1/2 convergence order fitted and pinned; the σ̂ estimator itself coverage-tested (0.950).
  • Adversarial discipline: every gate was first run against deliberately broken engines — a missing cosine factor, a double-counted Fresnel coefficient, biased roulette, correlated random streams, wrongly-shaped scatter — and the suite records which gate kills which defect. A gate that cannot catch the bug it exists for is not a gate.
  • Independent oracles: the same scenes run in two unrelated open-source Monte-Carlo tracers (Mitsuba 3, Raysect) agree with this engine within combined statistical error — 28/28 comparisons, and again on five fresh scenes at the engine-verification gate, 49/49.
  • The browser engine specifically reproduces the reference implementation’s frozen results and passes the identical gate suite in TypeScript; its acceleration structure (BVH) is gated to be bit-identical to the brute-force intersection scan, so speed never changes an answer.

13. What this page does not claim

  1. Numerical precision is not model accuracy. The ledger closing at 1e-13 says the arithmetic is right, not that a ρ you guessed is. The output is only as good as the reflectances and indices you put in.
  2. Every estimate is statistical. A bin’s value is estimate ± σ̂; treat differences smaller than a few σ̂ as unresolved. The hatching and lit-fraction warnings (§4) are there to be believed.
  3. Idealized surface models. P1 surfaces are ideal absorbers, ideal specular mirrors with scalar ρ, ideal Lambertian reflectors, and unpolarized-average Fresnel interfaces. Measured BSDFs, gloss models and polarization arrive with the scatter phase (P2+).
  4. Monochromatic-equivalent. One set of optical constants per run; no spectra, no dispersion in a single trace.
  5. No bulk absorption at P1. Glass loses power at its surfaces only; volume absorption activates at P2 with real media handling.
  6. Incoherent only. No interference, no diffraction — see the scope fence in §1. Wavelength-scale structures are outside the model’s validity whatever the error bar says.
  7. The P1 element set is deliberately small. Seven exact-geometry elements (§6). No round tube, no imported CAD; meshes arrive at P4 with an explicit accuracy label, precisely because a mesh cannot pass the machine-precision gates the analytic elements pass.
  8. Radiometric output only, for now. See §3.
  9. The tool analyzes; it does not design. It traces, finds and shows where the power goes. It will not synthesize a reflector or optimize a baffle for you — stating what a scene does, with an error bar, is the whole contract.

Try it: the Illumination Analyzer — start from a preset in §10 and check its anchor number against the run’s error bar yourself.

References

  1. R. Winston, J. C. Miñano, P. Benítez, Nonimaging Optics, Elsevier (2005), ch. 4 — CPC geometry, acceptance angle, edge-ray principle. [textbook]
  2. D. G. Goebel, “Generalized Integrating-Sphere Theory,” Applied Optics 6, 125 (1967). doi:10.1364/AO.6.000125.
  3. E. Fest, Stray Light Analysis and Control, SPIE Press (2013) — ghost analysis and baffle design context. [textbook]
  4. J. K. Salmon, M. A. Moraes, R. O. Dror, D. E. Shaw, “Parallel random numbers: as easy as 1, 2, 3,” SC’11. doi:10.1145/2063384.2063405 — the Philox RNG.
  5. E. Veach, “Robust Monte Carlo Methods for Light Transport Simulation,” PhD thesis, Stanford (1997); M. Pharr, W. Jakob, G. Humphreys, Physically Based Rendering — splitting and Russian-roulette unbiasedness. [textbook]