Design spec for the egui control panel overhaul. Addresses the
user-reported 'settings all look bad' by fixing the structural root
causes (flat 11-CollapsingHeader scroll, no styling, ragged sliders,
no presets) rather than a cosmetic reskin.
Key decisions captured:
- Chassis: right SidePanel (replaces floating Window)
- Theme: deep-space cyan/orange, hand-applied over Visuals::dark()
- Structure: 4 always-open framed cards + 6 collapsing sections
(11→10 groups; Renderer merges into Quality, fixing a latent
duplicate render_scale slider bug)
- Preset bar: Cinematic/Performance/Web/Custom with per-frame hash
detection of hand-edits
- Two-column Grid rows with unit suffixes + log scales on wide ranges
- Group-enable toggles in collapsing headers; standardized warning text
Non-goals explicit: no params/shader/physics changes, no custom font
binary, no painted toggle, no new deps.
The vertical epicyclic frequency's cross term is a√M/r^1.5 (radius to the
−1.5), following Okazaki 1987. The spec previously wrote a·Ω_φ/r, which makes
Ω_θ too large and breaks monotonic growth of precession with spin. Caught
during Task 1 implementation by the grows_with_spin test; syncing the spec
to the corrected formula that shipped in 891eadf.
Spec for 5-8 planets on Kerr circular orbits with strong-field Lense-Thirring
nodal precession. Path A: CPU computes position each frame, uploads to the
existing storage buffer; shader unchanged.
Physics: closed-form Ω_φ (Bardeen 1972 eqn 2.16) and Ω_θ (Caltech Ph236
epicyclic vertical frequency), giving exact nodal precession Ω_φ - Ω_θ.
χ=0 degenerates exactly to Schwarzschild (Ω_LT = 0, Newtonian Ω_φ).
Explicitly rejects Mino-time analytic geodesics (Fujita-Hikida): circular
orbits collapse the three-frequency decomposition to Ω_φ alone, elliptic
functions have no WGSL/std backing, and it would break physics.rs's
single-testable-mirror design. Closed-form Kerr frequencies are the right
tool for circular orbits.
Orbit radius bound to k·kerr_isco(χ), so planets track the disk inner edge
as spin changes and span the strong-field region (k=2.5 → r ∈ [1.25, 7.5]).
Random initial attitudes (ChaCha8Rng + UI seed) so the three orbital planes
precess at different Ω_LT rates — the visible Kerr signature.
Decomposes Planet into OrbitParams (immutable elements) + Planet (derived
center), keeps SphereData GPU layout untouched. Adds time_scale UI knob
because Ω_LT at r=8 needs ~25 min per revolution otherwise.
Design for replacing the smooth zero-thickness disk with a Gargantua-style
volumetric gas disk. Supersedes the Phase 3 non-goal "disk stays a zero-
thickness plane" - user feedback identified zero thickness as a root cause
of the disk looking too smooth.
Key decisions captured:
- Approach A volumetric integration: in-slab sampling reuses the existing
RK45 adaptive step (dense where light bends, sparse where straight),
no separate ray-march. Midplane edge-capture retained for straddling steps.
- Ridged multifractal noise (ridge^2) for sharp bright filaments, replacing
the smooth FBM blobs that produce the current mushy texture.
- Separate density field (smoothstep-gated FBM) for gas clumping, plus a
logarithmic-spiral arm modulation riding the Keplerian shear.
- DiskQuality tier enum (Off/Low/Medium/High) gates octave counts; Off is
a full revert to the flat disk as perf escape hatch + visual A/B.
- physics.rs untouched: volumetric integration is render-sampling layer,
never enters the geodesic solver; existing tests stay green.
10-task plan (Tasks 0-9) for the HDR bloom + FBM disk + ACES + AA
pipeline. Each task is a standalone commit: Rgba16Float offscreen →
FBM disk → gaussian-speck stars → brightpass → blur pyramid →
composite+ACES → BloomQuality enum → Quality panel → verification.
Conventions established upfront (camera orders, RenderLayers, the
QuadScaleFactor/CompositeQuad/Nudgable markers) so each task references
them rather than re-deriving. The naga var<private> array fix for the
blur kernel is baked into the shader from the start.
Design for raising the renderer from geometrically-correct-but-flat to
Gargantua-reference fidelity. Four user-selected traits:
- HDR color + ACES tone mapping (Rgba16Float offscreen, Narkowicz fit)
- Multi-pass HDR bloom (bright-pass → down-pyramid → up-pyramid → composite)
- Domain-warped FBM disk texture (replaces two-sine noise)
- Anti-aliasing via render_scale + gaussian-speck stars
All quality options configurable via a dedicated egui Quality panel,
with tiered web defaults (Low bloom, no MSAA/star-AA) vs desktop (High).
BloomQuality::Off falls back to the original LDR path for WebGPU
browsers without float-filterable support.
Geodesic integrator (deriv/rk45_step/is_captured_rk45) untouched —
the physics.rs mirror contract is unaffected. No new tests.
The docs described Phase 2 as 'future work' while the code had already
shipped it: spin is wired through the uniform into the shader's Kerr deriv(),
the integrator is adaptive RK45, disk_inner is ISCO-derived, render_scale
runs a real offscreen render-to-texture + upscale pass, and the UI exposes a
Spin slider with live ISCO/Horizon readouts. Anyone reading the docs got a
wrong picture of completeness.
README:
- Intro: 'Schwarzschild' -> 'black-hole (Kerr at spin>0, Schwarzschild at 0)'.
- How it works: RK4 -> adaptive Dormand-Prince RK45; add the frame-dragging
term to the bending accel; capture radius r+(chi); ISCO-tracked inner edge.
- Controls: add Black Hole section (Spin, ISCO/Horizon); render_scale slider.
- Performance: render_scale now wired (0.75 desktop / 0.5 web), not reserved.
- Status: Phase 1 shipped; Phase 2 implemented-pending-human-validation;
Phase 3 (exact pseudo-Hamiltonian) is the actual future work.
AGENTS.md:
- Intro + mirror contract: name the Kerr/RK45 functions the mirror must track
(kerr_bending_accel, rk45_step, is_captured_rk45) and the exact shader lines.
- Conventions: 'render_scale and spin are reserved' is false now — both wired;
update the perf-lever and web-defaults notes accordingly.
- Reference docs: list both Phase 2 docs, not just Phase 1.
Phase 2 plan (docs/superpowers/plans/2026-07-13-...-kerr.md):
- Status banner: Tasks 1-7 implemented+committed, Task 8 (human visual/perf
checklist) is what remains.
- Check the Task 1-7 step/commit boxes; leave all Task 8 manual steps and the
visual/fps acceptance items unchecked. Check only the code-verifiable
acceptance items (cargo test green, RK45+render_scale running, Spin slider
shipped).
- Material2d bind group is group 2 (#{MATERIAL_BIND_GROUP}), not group 1
- RenderPlugin has no wgpu_backends field; enable bevy 'webgpu' feature instead
- WgpuSettings::default() auto-selects BROWSER_WEBGPU on wasm32
- Imports from bevy::sprite_render (Material2d, AlphaMode2d)
- Component-based spawning (Camera2d, Mesh2d/MeshMaterial2d), no bundles
- getrandom 0.4/wasm_js handled transitively by Bevy