- Pooled spark bursts (PORTED highway_3d, pool 160) at the struck lane,
timing-colored via _timingHex/_classifyTiming (±50ms window, inner 40%
= on-time); streak-scaled counts (streakFx)
- Lane flashes resurrected as pooled additive gauss-tex quads at the hit
line (timing-colored; red for wrong hits); kick = full-width quad
- Kick pulse: camera dip + amber floor wash, exp decay, hitFx-scaled
- Approach highlight: lane stripes brighten toward their next note
- Open hi-hat: hh_open renders a warm ring around the gem (closes TODO);
orthogonal to accent/ghost/flam variants
- Settings: Hit sparks / Timing colours / Streak feedback toggles +
Hit feedback intensity slider (drum_h3d_bg_*, live-applying)
- All FX resources pooled/shared, disposed in BOTH teardown paths
- Tests: _classifyTiming boundaries + FX defaults (10 total)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- Consume host adaptive-quality bundle.renderScale; fold into DPR like
highway_3d (splitscreen proxy: >1 instance caps baseDPR at 1.25)
- Bloom: port _bloomEnsure/_bloomDispose (UnrealBloomPass 0.65/0.5/0.82,
MSAA HalfFloat target, ACES<->None tone-mapping switch); rebuilt across
the kit-change renderer recreation; direct render is the degrade path
- FX settings scaffold: FX_DEFAULTS + readFxSettings + drumH3dSetFx
(drum_h3d_bg_* keys), Graphics section in settings.html (bloom toggle,
default ON, live-applies)
- _applyLaneFlashes dead-code comment updated (visual consumer lands in
the hit-FX PR)
- __test export + tests/data_layer.test.js (vm harness, 8 tests) —
picked up by the CI glob from the bundling PR; README refreshed
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>