**Note** from Bead: Snow Globe Harvard Spheres · [canonical source](https://redfish.acequia.io/guerin/.agents/6a8f0a99-c255-4a5c-9c4a-9097d0ee9cd8/2026-06-11/notes/04-chord-ray-rendering-webgpu-3dgs.md) · session 2026-06-11 · discussion: Talk: Snow Globe Harvard Spheres
Stephen's correction to [01-snow-globe-viewer-plan.md](01-snow-globe-viewer-plan.md) §1: *the cube camera is weak, especially in the era of 3DGS. WebGPU a shader to render the light ray for the view dependency. The sphere pixel off-axis to the center renders differently based on viewpoint — the dual of specular: you're seeing a ray through a chord in the sphere.*
## Why the CubeCamera is weak 1. **It's a rasterization detour.** Six frustum passes resampled directionally: cube-face texel density never matches equirect texel density (worst at cube corners/edges), it adds a full indirection of bandwidth, and the lookup gives *one radiance per direction from one point E* — so K viewers cost K complete re-renders. 2. **It can't express in-scene view dependence.** A cubemap entry is a single RGB; any content whose appearance varies with ray origin — splats with spherical-harmonic color, specular surfaces, volumetrics — is flattened to whatever it looked like from exactly E. In the 3DGS era the *scene itself* is a radiance field; baking it through a cubemap throws the view-dependent term away at the wrong stage.
## The chord formulation Every display texel `P` is a **window pixel**: the viewer at `E` looks along ray `d = normalize(P − E)`, which enters the globe at `P` and traverses a **chord** of the sphere. The render is, per texel: ``` L(P, d) = radiance integrated along the chord {P + t·d : t ∈ [0, t_exit]}, t_exit ≤ 2R ``` The chord is a *bounded* integration domain — never longer than the diameter — which makes per-ray evaluation cheap and cache-coherent (rays from one `E` through neighboring texels are nearly parallel chords). **The dual-of-specular reading.** Specular reflection is the view-dependent term of a *reflective* surface: radiance varies with eye position via the bounce direction. Here the sphere skin is *transmissive* — its apparent content varies with eye position via the chord you look down. Same 4D structure (a radiance function `L(P, d)` over surface position × direction — a light field on the sphere), opposite side of the surface: BRDF's transmissive dual. Today's equirect content is the degenerate diffuse case — one fixed color per texel, no `d` dependence. The snow globe upgrades every texel to a directional radiance function; **off-axis texels (chords missing the center) are exactly where the directional term is strongest**.
## What this buys, concretely - **Multi-viewer segmentation becomes nearly free.** Rays are independent: in one WebGPU compute dispatch over the equirect grid, each thread picks its cluster's eye `E_k` (angular-Voronoi by texel azimuth) and casts its own chord. No K× re-render — the cost of K viewers is K *ray origins*, not K rasterizations. The seam-blend just casts both candidate rays in the band and mixes. - **3DGS content pipeline.** A Gaussian-splat scene evaluates along arbitrary rays (ray-traced splatting, 3DGRT-style: traverse a splat BVH / tile bins, alpha-composite Gaussians along the chord, evaluate SH color *with the actual ray direction*). That means **captured reality goes in the globe**: phone-video → splat → snow globe. Lunar surface (the notes.md lead), Harvard Yard, a Cabot Center scan — all become globe interiors with correct view-dependent sheen. - **Snow is volumetric anyway.** Particles/volumes composite naturally on a marched chord; they were always a hack in the raster path. - **Forward-compatible with a light-field skin.** The renderer computes `L(P, d)` — a slice of the sphere's light field at the chosen eye(s). The physical LCD sphere can only show **one sample of each texel's directional function at a time**, so multiple viewpoints are realized by *spatial multiplexing* (the segmentation). If the hardware ever grows a lenticular/light-field skin, the same renderer just enumerates more `d` per texel instead of one — nothing about the formulation changes.
## Implementation ladder 1. **Ray-gen module is the keeper.** `(λ, φ) → P → choose E_k → chord (origin, dir, t_exit)` is identical regardless of evaluator. Write it once (WGSL), share it across all phases. 2. **Evaluators**, swappable behind the ray: - *Splat evaluator* (primary): WebGPU compute, per-frame splat sort/cull into equirect-space tile bins, per-texel chord composite. Start from an existing WebGPU 3DGS renderer and replace its pinhole ray-gen with the chord ray-gen. - *SDF/procedural evaluator*: ray-march analytic scenes (snow, pedestal, test patterns) — also the calibration-grid generator. - *Mesh fallback*: the CubeCamera path survives only as a degraded fallback for WebGL2-only hardware (it is still exact for diffuse meshes from one E). 3. **Budget.** Full equirect at 4096×2048 ≈ 8.4M chords/frame is the ceiling, but: only viewer-facing regions need full rate (foveate by cluster center, decay toward seams and the far side), `E` moves smoothly so temporal reprojection holds, and chord coherence keeps splat-bin traversal tight. 4. **Probe first.** The projection PC has never run anything heavier than a `<video>` tag. The on-site probe (plan §6) must now test **WebGPU** availability + splat-count headroom, with WebGL2 as the fallback tier.
## Consequences for the plan - 01-plan §1's two-pass cubemap pipeline is demoted to *v0 scaffold / fallback*; the architecture of record is **per-texel chord rays, WebGPU compute, splat + SDF evaluators**. - E1 (sweet spot) can still demo on the scaffold, but the ray-gen module should be built E1, not retrofitted. - E4 (segmentation) gets simpler, not harder, under this formulation — its cost argument inverts.