feat(gui): WAVE showcase visualizations — 3D Ridge, Tunnel, Horizon (stacked on #3955)#3991
Conversation
Bridge grabs of the three wavedemo.frag scenes (live FLEX-8400M RX) and the Scope-mode regression check, referenced from PR aethersdr#3991. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three GPU-only, audio-reactive scenes for the WAVE scope (wavedemo.frag, one extra pipeline over the same fullscreen quad). Demoscene rules: fully analytic, palette entirely from the active theme (accent / bright / success / warning / danger over the theme background — a theme switch recolors the whole show), and every scene keeps moving in an ambient attract mode when no audio flows. - 3D Ridge: hidden-line perspective heightfield of the envelope's last ~3 s (Joy Division × 3DSS) — dark mountain bodies, theme-bright crests, star field. Fed by a 256×96 R32F history ring texture that costs one 1 KB row upload per ~33 ms. - Tunnel: Amiga demo tunnel. The live waveform columns ARE the wall texture, mid-band energy launches bright rings down the bore, high band warms the spokes, RMS breathes the core; low band sways the vanishing point. - Horizon: synthwave grid. The live waveform IS the mountain skyline, a scanline sun swells with RMS, grid speed rides the low band, peaks flash the horizon line. Plumbing: three new ViewMode values + combo entries (GPU builds only — CPU builds fall back to Graph and never offer them), fixed 256-column reduction + 12-band Goertzel energies per frame, ~150 B uniform block. Measured 213–220 µs/frame at 60 fps — showcase costs the same as the utility modes. Classic modes regression-checked; -DAETHER_GPU_SPECTRUM=OFF configuration builds and runs clean (the aethersdr#3955 Linux lesson). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bridge grabs of the three wavedemo.frag scenes (live FLEX-8400M RX) and the Scope-mode regression check, referenced from PR aethersdr#3991. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3ff876f to
4863629
Compare
ten9876
left a comment
There was a problem hiding this comment.
Review: request changes
Rebased onto current main (dropped #3955's now-merged commits; resolved the one renderGpuFrame keep-both conflict), both AETHER_GPU_SPECTRUM on/off configs build clean. The showcase itself is nicely crafted — the std140 uniform contract, history ring-index math, and enum/CPU-build safety all verified clean. But the review (multi-agent + adversarial verify) found a shared-path regression, a robustness issue that gates all GPU rendering, and a functional gap. Each inline comment carries a fix (apply-able suggestion, or a sketch where it spans files).
Blocking:
- texSize truncation regresses the shared non-demo path — 1px texture/image mismatch on fractional-DPR displays affects Graph/Bars/overlay (already-merged rendering), not just demo.
- A demo-only shader failure blanks the entire GPU widget + leaks per frame — the optional demo pipeline shouldn't be a hard prerequisite in the readiness guard.
Should fix in this pass:
3. Demo scenes freeze at idle — no animation timer, so the attract-mode/timeSec motion the shader is built around never runs without live audio.
4. Ridge reads an uninitialized history texture (~3 s of garbage on first entry / after device-loss) — seed it to zero.
5. NaN reaches the UBO — std::clamp doesn't sanitize; guard rms/peak/energy.
Notes (fast-follow): shader visual robustness (atan(0,0), horizon moiré, timeSec precision, negative-star), the ~96-tap Ridge loop cost, and a dead zoom uniform + demo-scene footer.
The core design (dedicated demo pipeline, procedural theme-driven scenes) is sound. I can push fixes for 1–5 if you'd like.
…solation, idle animation, hist seed, NaN guard (aethersdr#3991) Review follow-ups for the showcase visualizations. - texSize: size the grid/overlay textures with `size()*dpr` (qRound), matching m_gridCache/m_overlayImage, instead of truncating — a 1px mismatch on fractional DPR size-mismatched uploadTexture on the SHARED (non-demo) grid + overlay path (Graph/Bars). Fixes both the init and the render-path sizing. - Demo pipeline isolation: drop m_demoPipeline from the initialize() readiness guard and gate the demo branch on it via `demo`. A missing/failed wavedemo.frag no longer blanks the whole GPU widget (Graph/Bars still render) and no longer re-inits every frame (unbounded QRhi leak); demo modes fall back to Graph. - Idle animation: the demo scenes animate continuously (attract mode) but repaints are data-driven, so they froze without live audio. Drive ~60 fps repaints via m_demoAnimTimer only while a demo mode is active. - History ring: zero-seed m_histTex once (m_histCleared) so Ridge doesn't sample undefined GPU memory (garbage/NaN ridgelines) for ~3 s on first entry and after every device-loss re-init; reset the flag + m_histHead in releaseResources(). - NaN: std::clamp doesn't sanitize NaN — guard rms/peak/energy before the UBO upload so a degenerate reduction can't blacken the frame. Both AETHER_GPU_SPECTRUM on/off configs build clean. Fixes Are Demonstrated (Principle XI). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed fixes for the blocking + confirmed findings (commit `ba187aca`). Both `AETHER_GPU_SPECTRUM` on/off configs build clean locally.
Deferred as fast-follows (advisory, non-blocking): the shader visual-robustness polish (atan(0,0), horizon moiré, timeSec precision, negative-star), the ~96-tap Ridge loop cost, and the dead |
ten9876
left a comment
There was a problem hiding this comment.
Approving the showcase after the rebase + review-follow-up fixes (texSize shared-path fix, demo-pipeline isolation, idle animation timer, history-ring seed, NaN guard). Both AETHER_GPU_SPECTRUM configs build clean locally; all review threads resolved. Set to auto-merge on CI.
Summary
Three GPU-only, audio-reactive showcase visualizations for the WAVE scope — crossing the line from utility to fun, deliberately. One new fragment shader (
wavedemo.frag), one extra pipeline over the existing fullscreen quad, zero new dependencies. Demoscene rules: fully analytic scenes, the palette comes entirely from the active theme (a theme switch recolors the whole show), and every scene keeps animating in an ambient attract mode when no audio is flowing — the screen is never dead.Contained & cheap
ViewModevalues + WAVE drawer combo entries (GPU builds only — CPU builds fall back to Graph and never offer them; a persisted demo mode degrades gracefully).get wavestats— the showcase modes cost the same as the utility modes.-DAETHER_GPU_SPECTRUM=OFFconfiguration builds and runs clean (the perf(gui): WAVE scope — incremental reduction + QRhi GPU render, wavestats/scrollTo bridge verbs (Phases 1+2) #3955 Linux lesson, applied preemptively this time).Screenshots (live RX on the FLEX-8400M)
Horizon:
Proof
Bridge grabs of all three scenes live on the FLEX-8400M (RX band noise as input — voice input makes Ridge/Horizon dramatically more mountainous), plus a Scope-mode regression grab. Perf numbers from
get wavestatsper mode.💻 Generated with Claude Code (Opus 4.8) with architecture by @jensenpat