Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map3d-flight/.nornir/scatter-lut-gpu-design.md

GPU scattering-LUT precompute pass — design

The chosen design for FLIGHT-SIM #7 (roadmap §2-GPU): move the atmospheric transmittance LUT generation off the CPU and onto the GPU as a compute pass, keep the CPU model (atmos.rs) as the reference oracle + fallback, and produce a sampled GPU texture as the seam a future sky.wgsl reads. Behind the wgpu feature; the landed 21-pass facett-map3d pipeline is untouched (L2 additive, no regression).

The pieces (src/scatter_gpu.rs + src/scatter_lut.wgsl)

Why the CPU model stays (L2 / L5a)

The compute shader is a twin, not a replacement. atmos::TransmittanceLut remains (a) the fallback for hosts with no adapter (wasm / a GPU-less laptop / a deck pane) and (b) the oracle the GPU output is validated against. The LUT type + the SunSky seam are reused from the existing modules, never forked — this pass only adds a GPU producer behind them.

The horizon-tangent knife-edge (the one real subtlety)

The near ray/ground intersection t = -rμ − √(r²(μ²−1)+R_g²) suffers catastrophic cancellation at the horizon tangent (where the two terms are nearly equal and the root collapses toward 0). There, CPU-f32 and GPU-f32 round the sqrt to opposite sides of the ground-hit branch, so a single texel per altitude row flips between "hits ground (short path, T≈1)" and "misses (long grazing path, T≈0)". This is a property of the model at the tangent, and it lands entirely in the μ < 0 (below-local-horizon) band — the occluded region a sun-transmittance lookup never samples (a sun below the horizon is blocked). So parity is judged on the sampled region: max_err_upper over μ ≥ 0 must be < 5e-4 (observed ~2e-5), and the > 1e-2 outliers must be ≤ h+2 and all below the horizon — proving the divergence is the degenerate tangent line, not a shader bug.

Alternatives rejected