Caustic Light Art With Ray Bundles
A seeded surface refracts normalized ray bundles into an irradiance map, with convergence checks, explicit indices, and a bounded generative-light claim.
Caustic light art can begin with a real geometric idea: neighboring rays refract through a changing surface and concentrate unevenly on a receiver. The bright folds are an accumulated density field, not a glow filter drawn after the fact.
This generative light study authors a seeded one-dimensional surface, applies Snell's law to sampled ray bundles, conserves normalized sample energy, and checks convergence. It is geometric optics with explicit omissions, not a full physical renderer or laboratory prediction.
Define caustic light art as a bounded model
The scene contains parallel incoming rays, a transparent interface described by a height function, refractive indices for the two media, and a flat receiver a fixed distance away. Rays intersect the interface once, refract according to the local normal, and deposit equal normalized energy into receiver bins. The study omits Fresnel reflection, absorption, dispersion, polarization, multiple internal bounces, wave interference, volumetric scattering, and finite light sources. Naming those omissions protects the visual from borrowed scientific authority while giving the algorithm a precise, inspectable core.
- 1Surface
Seed height + normal
- 2Refract
Apply Snell's law
- 3Accumulate
Conserve sample energy
- 4Direct
Map stable field
Author a seeded refractive surface
Build the interface from a small basis of sinusoidal components whose amplitudes, frequencies, phases, and envelope come from a named seed. Compute both height and derivative analytically where possible so local normals remain stable. Bound the slope to avoid pathological folding or numerical intersections in this single-interface model.
The surface should be art-directed: one low frequency establishes broad folds, a middle component creates branching rhythm, and a small component introduces grain. Store parameters and a sampled surface hash so every later irradiance map can be traced to the same geometry.
Apply Snell's law with explicit orientation
At each intersection, orient the normal against the incident ray and use the ratio of refractive indices to compute the transmitted angle or vector. Clamp only for floating-point protection, not to hide invalid geometry. If the chosen direction supports total internal reflection, classify it rather than forcing a transmitted ray; this simple outside-to-denser-medium fixture does not encounter that branch.
Verify normal incidence, symmetry, and known-angle cases before tracing an image. The reference material explains dielectric scattering in a fuller renderer, while this article keeps a narrow two-dimensional ray refraction construction.
Accumulate a normalized irradiance map
Project every transmitted ray to the receiver, then splat its weight across one or more bins using a documented kernel. Each ray contributes one divided by ray count so total sample energy remains one before cropping; bright areas reflect concentration rather than added energy. Record escaped or out-of-frame energy separately.
A nearest-bin accumulator is easy to inspect but can alias; linear splatting or a compact filter yields smoother convergence. Do not normalize every final image independently without retaining absolute density, because that would make different surfaces appear equally energetic and erase useful comparison.
Runnable artifact: The deterministic accumulator refracts 256 rays through a seeded sinusoidal normal field, conserves total sample energy, and hashes the receiver bins. Its snell-ray-accumulator.test.mjs receipt keeps the article's simplified boundary executable and reviewable.
Save the inspectable proof as snell-ray-accumulator.test.mjs and run node snell-ray-accumulator.test.mjs. Expected final line: PASS: caustic field deterministic.
import assert from "node:assert/strict";import crypto from "node:crypto";
const refract=(theta,n1,n2)=>Math.asin(Math.max(-1,Math.min(1,n1/n2*Math.sin(theta))));const field=Array(32).fill(0);for(let i=0;i<256;i++){const x=i/255,normal=.35*Math.sin(x*Math.PI*4),out=refract(-normal,1,1.5)+normal,target=Math.max(0,Math.min(31,Math.round((x+Math.tan(out)*.3)*31)));field[target]+=1/256}const energy=field.reduce((a,b)=>a+b,0);assert.ok(Math.abs(energy-1)<1e-12);const hash=crypto.createHash("sha256").update(JSON.stringify(field)).digest("hex");assert.equal(hash.length,64);console.log("PASS: caustic field deterministic");
Measure convergence before styling
Render the same surface at increasing ray counts—such as 1k, 4k, 16k, and 64k—and compare normalized fields with a fixed error measure and the same receiver grid. Inspect whether fold positions stabilize and whether residual noise decreases. Increase receiver resolution separately so sample count and pixel count do not change together.
A deterministic low-discrepancy sequence can reduce variance, but its generator and ordering belong in the receipt. Stop when additional rays no longer change the intended print-scale structure within the chosen tolerance, not when a desktop GPU reaches an arbitrary round number.
| Parameter | Low | Reference | High |
|---|---|---|---|
| Index ratio | Soft bend | Glass-like fixture | Strong fold |
| Surface amplitude | Broad field | Branch rhythm | Fold risk |
| Receiver distance | Near detail | Balanced | Spread |
| Exposure | Linear | Directed | Clipped |
Art-direct the field without hiding evidence
Map irradiance through a disclosed exposure curve and limited palette. A dark ground with warm folds can evoke sunlight in water, while a pale field with ink-like contours can feel diagrammatic. Reserve clipping for intentional highlights and keep a diagnostic linear grayscale image beside the final.
Add cropping, negative space, and typography after the field is stable; do not move bright folds by painting. The parameter contact sheet varies one dimension at a time—index ratio, receiver distance, surface amplitude, or exposure—so aesthetic choices remain connected to the generative system.
Move from CPU reference to WebGPU carefully
Keep a small CPU implementation as the correctness oracle, then parallelize ray generation and receiver accumulation in WebGPU for interactive exploration. Choose accumulation precision and strategy based on device support; atomic operations, workgroup reductions, and multi-pass buffers have different constraints. Compare a fixed low-resolution GPU field with the CPU reference within a declared tolerance before trusting large renders.
Bound buffer sizes and dispatch dimensions, handle device loss, and retain a static fallback. Performance measurements name browser, adapter, resolution, rays, and warm-up rather than presenting one machine as a universal speed claim.
Publish a reproducible generative light study
Archive surface parameters, indices, receiver geometry, sampler, ray count, accumulator settings, linear field, styled export, code version, and output hashes. Include the convergence contact sheet and model-limit statement beside the final work. If the piece is printed, record dimensions, profile, paper, proof adjustments, and the fact that display luminance differs from reflected ink. The work becomes more compelling when the visual and its technical restraint reinforce each other: viewers can see the ray logic, reproduce the field, and still encounter a deliberate composition rather than a benchmark screenshot.
Separate optics, compute, and artistic precedent
PBRT's dielectric BSDF chapter supplies a fuller rendering context, the WebGPU specification constrains the parallel implementation, and OpenStax's refraction chapter keeps the underlying geometry legible. The site's related studies—WebGPU generative art, minimal surfaces, reaction-diffusion fields, and SDF typography—offer composition and shader patterns while leaving the ray model's limits visible.
Watch the fold appear across four ray counts
Freeze the surface seed, refractive indices, receiver geometry, and exposure, then render the linear field at four increasing sample counts on the same grid. Difference adjacent fields, track peak motion and escaped energy, and view every diagnostic at final print scale before choosing a stopping threshold. Caustic light art gains both visual tension and technical honesty when the bright fold survives convergence while small sparkles are recognized as sampling noise; palette and typography can then respond to the stable structure without painting over the model.
Save the linear receiver field before exposure and palette mapping, then compare its hash and total energy across the CPU reference and GPU path. A caustic light art edition can change crop, paper, or color direction later while still proving that the optical construction—rather than a painted highlight—created the underlying fold.
Perturb one surface coefficient by a documented amount and render the same sample ladder again. This second caustic light art study shows whether the composition is robust enough for intentional art direction or balanced on numerical noise, and it makes the authored surface itself part of the visible creative argument.
| Decision | Evidence retained | Stop condition |
|---|---|---|
| Define caustic light art as a bounded model | coordinate system, light direction, surface equation, medium indices, receiver geometry, included effects, and explicit omissions | the image is described as physically accurate water or glass without modeling its defining conditions |
| Author a seeded refractive surface | seed, component table, height and derivative functions, slope bound, sampling domain, surface hash, and rejected extreme parameters | random noise changes on every frame or produces normals the model cannot handle |
| Apply Snell's law with explicit orientation | incident vector, oriented normal, n1 and n2, transmitted direction, total-internal-reflection branch, and analytic fixtures | angles mix degrees and radians or the normal flips unpredictably across the surface |
| Accumulate a normalized irradiance map | ray count, per-ray weight, receiver bounds and bins, splat kernel, in-frame and escaped energy, peak density, and field hash | brightness comes from an arbitrary blur that cannot conserve or account for sample weight |
| Measure convergence before styling | ray-count ladder, receiver resolution, sampler, fixed surface, field difference, peak movement, runtime context, and chosen stop | the prettiest high-sample render is published without a lower-sample comparison |
| Art-direct the field without hiding evidence | linear field hash, exposure curve, palette values, clipping percentage, crop, typography layer, and one-variable contact sheet | manual paint changes are merged into the generated light field without provenance |
| Move from CPU reference to WebGPU carefully | CPU reference hash, shader and pipeline versions, buffer formats, dispatch geometry, comparison tolerance, device details, and fallback image | a fast shader is accepted because it looks similar while losing energy or shifting folds |
| Publish a reproducible generative light study | complete scene manifest, model-limit note, convergence evidence, reference and styled hashes, print proof if any, edition ID, and revisit trigger | only the final raster survives after parameters and diagnostic fields are discarded |
Caustic light art becomes richer when the ray construction and its omissions remain visible beneath the styling. Preserve the surface parameters, normalized field, convergence sheet, and edition output together.