Strategy 32 follows a sampled light-ray family through actual triangle meshes, then gathers the refracted sheets in a participating medium. It extends the hourglass experiment to concave objects, holes, changing surface normals and chains of separated glass solids. The older analytical sphere hourglass remains strategy 20.
Three related modes, not one rasterizer
| Mode | Support construction | Camera evaluation | Accuracy character |
|---|---|---|---|
| Analytical hourglass 20 | Exact axis-revolved sheet for an analytical sphere (plus its selected chain extensions) | Solve camera-ray/sheet crossings with the analytical Jacobian | No finite angular tessellation for the one-sphere sheet; still subject to the documented support limits and optional Jacobian guard |
| Mesh sheets 32, normal | Trace a finite angular ray family through triangle meshes, adaptively join matching path histories into triangles | Intersect each camera ray with the sheet BVH and evaluate the local projected Jacobian | Approximate finite angular quadrature; increasing passes removes Monte Carlo noise, while increasing angular resolution reduces discretization error |
| Fast structure preview on 20 or 32 | Reuse the corresponding analytical or mesh-derived sheet triangles | Project and rasterize triangles into a reduced-resolution screen buffer, then optionally filter and enlarge it | Deliberately biased viewfinder; reduced resolution, interpolation, a grazing clamp, filtering and incomplete camera-side visibility remain |
Strategy 32 can handle difficult shapes because it replaces the sphere-specific closed-form construction with traced mesh rays. Bias is not what grants that support. The normal mode is already an approximation because a continuous ray family is represented by finitely many angular samples, but it still evaluates camera intersections in scene space. The fast toggle introduces a second, more aggressive approximation by moving that gather into screen space.
The useful mental model is therefore: 20 derives the sheet, 32 reconstructs the sheet numerically, and Fast preview draws either sheet as a filtered image.
The fast image may reveal a narrow fold much sooner because fractional pixel coverage draws geometry that no stochastic camera sample happened to hit. Its grazing floor and blur also tame extreme Jacobian values. This explains the clean early image, but it is exactly where additional bias enters: these regularizers change the limiting image rather than merely reducing noise.
Open a complete experiment
Run Mesh-Photon-Sheets.bat in the RadianceLab folder and choose a subject.
Each launch gets a separate runtime directory, leaving ordinary viewer settings
alone. Alternatively use File → Scene Presets → Mesh photon sheets [32, ready to render]
inside the viewer. The menu sets the estimator, camera, medium and display
defaults together; no separate estimator selection is needed.
| Preset | Subject | What to inspect |
|---|---|---|
| 83 | Suzanne, the Blender monkey | Concave geometry and asymmetric refracted sheets |
| 84 | Utah teapot | Body, handle, spout and lid in a closed glass casting |
| 85 | Three triangulated spheres | Familiar focusing geometry rendered as meshes |
| 86 | Glass torus | Multiple intersections around a hole |
| 87 | Four glass bodies | Caustic segments between bodies and beyond the last one |
The monkey and teapot assets were repaired into watertight, consistently oriented solid castings. In particular, this teapot is a solid refractor, not a hollow glass vessel. The asset record retains the source files, licenses, conversion procedure and topology checks.
The paired scenes initially isolate refracted fog. Enable Direct fog context to add the ordinary, unbent illumination of the medium. The initial display is a path-family view; hiding that component is not a change to the underlying scattering coefficient. Glass and stage surfaces can remain visible independently. The striped background in the single-object scenes is scene geometry, so its distortion is produced by the glass camera rays.
From a ray family to a mesh sheet
- Sample a light point and azimuth. Sweep the polar angle through a finite set of rays. Each ray follows Snell refraction, Fresnel transmission and internal total reflection through the glass.
- Record the outgoing medium intervals after each glass traversal. Adjacent rays can be joined only when their entry/exit history and terminal geometry agree. Rapid changes trigger local angular subdivision; unresolved branch boundaries are dropped rather than bridged.
- Join matching intervals into two-triangle strips. A camera ray gathers all strips it crosses, using their projected Jacobians, local scattering, phase function and attenuation on both sides of the connection.
- Average independent light/azimuth batches over time. Mesh geometry is cached in a BVH and shared across the frame. Moving the camera resets accumulation; holding it still refines the image.
For a parameter chart X(theta,t), the geometric factor is
J = |(dX/dtheta × dX/dt) · camera_direction|.
The input measure includes sin(theta) dtheta dt and 1/p(azimuth) = 2*pi.
Each triangle carries its parameter-cell extent, so finer tessellation does not
add light merely by adding triangles. The denominator is the projected
triangle cross product; its associated parameter area is included in the
numerator. There is no normalization by the number of successful intersections.
Quality controls
- Rays along each sheet: resolves angular curvature and branch boundaries.
- Sheets per pass: more independent azimuth/light samples per displayed pass.
- Glass interfaces: entry and exit each count once; four solids need at least eight interfaces. Internal reflections also use the budget.
- Smooth glass normals: interpolated vertex normals versus literal facets. Geometric sidedness still prevents a smoothed normal from sending a transmitted ray back through the face it entered.
- Max bend between rays: prompts refinement; unresolved large changes are discarded. Compare resolutions when a narrow feature appears to be missing.
- Grazing cutoff: a dimensionless camera/sheet cosine threshold, independent of triangle size. A nonzero threshold removes some grazing contributions.
- Full viewport resolution: use for a still image; half resolution reduces the cost while framing a view.
Research scope
This is finite angular quadrature with Monte Carlo light/azimuth sampling, not an exact or unbiased arbitrary-mesh version of the sphere solver. More passes reduce sampling noise; they do not eliminate a fixed angular resolution's discretization error. The angle threshold, unresolved topology changes and grazing cutoff can discard energy. Compare both sample count and angular resolution before treating an image as converged.
Current support is closed, nonoverlapping dielectric solids, scalar central IOR in RGB, homogeneous media and one volume-scattering event after a transmitted glass chain. The light-side family includes transmission and internal total reflection; it does not include every externally reflected or multiply scattered path. Camera rays can reflect and refract through the mesh. The stage uses direct surface lighting; this mode does not yet add the focused surface caustic on the floor. Analytical compositing/MIS and correlated-raster settings from the older modes are not applied to this separate renderer.
Reproduce validation
The native validation report includes all five rendered scenes, timings, angular-resolution comparisons and the four-body chain through eight glass interfaces. The paired presets use exposure 10; the launcher starts with those scene-specific camera and display defaults.
cmake --build build --config Release --target PrismMeshSheetTest
build/bin/Release/PrismMeshSheetTest.exe
python docs/mesh-photon-sheets/validate_renders.py build/mesh-sheet-validation smoke --passes 64 --width 480 --height 300
python docs/mesh-photon-sheets/validate_renders.py build/mesh-sheet-validation chain --passes 64
python docs/mesh-photon-sheets/validate_renders.py build/mesh-sheet-validation refinement --passes 64
The native runner retains float films, display PNGs, exact configuration, binary hashes, timing and sheet counts by interface depth. Image differences are diagnostics, not a ground-truth error estimate. Use a fresh run directory after rebuilding: the runner refuses to mix different executable versions.