Expand description
GPU compute-particle scenes: strange attractors (ADR-0015, Plan 0016). The
engine’s first compute pipeline — a storage buffer of particles stepped
through an attractor map each frame by a compute shader, then drawn as
additive point-sprites with fading trails. This is idiom B of the four render
idioms; the CPU swarm is idiom B’s ~10k CPU precursor,
replaced here by GPU-resident state that scales to 100k+ points with no CPU
round-trip.
Trails reuse Plan 0014’s PingPongField rather
than a second feedback mechanism: each frame the previous accumulation texture
is drawn back faded (decay pass), the fresh points are added on top
(additive), and the result is composited to the surface (present pass). Trail
persistence is the named fade parameter; fade = 0 clears the accumulation
each frame, reproducing the trail-free look.
Every knob is an ADR-0002 layer-2 named parameter — the attractor
coefficients (a,b,c,d), look scalars (size,hue,fade), and a
beat-driven reseed — so a preset steers the cloud’s shape and a beat
disturbs it. All randomness is the seeded initial scatter plus the reseed’s
deterministic per-particle kick (NFR 6): the
point cloud is a pure function of the seed and the fixed-dt step sequence,
so a capture reproduces bit-for-bit on one adapter.
GPU resources are built lazily, on first render — the same discipline the
reaction-diffusion scene uses (see its module docs). create_all builds every
scene up front, but the compute pipeline + storage buffer + trail field are
constructed only when this scene is first drawn, so a capture that never
activates it never builds them (keeping the other scenes’ WARP captures
unperturbed).
The accumulation field is sized to the render target and capped (Plan 0027
Phase 2, now the tier’s attractor_trail_cap) rather than fixed at
640x360, so the present is close to 1:1 up to the cap instead of a soft
upscale on a 1080p+ display. That size is quantized to TRAIL_GRID_STEP,
so a live window drag re-allocates the field a handful of times rather
than once per frame.
The field’s own aspect is not the projection’s (Plan 0029 Phase 5). The
present is a plain stretch (aspect ignored, as the reaction-diffusion present
does), so a point at field NDC x lands at target NDC x — the field’s aspect
cancels out and the projection must use the target’s. Quantization makes
the two genuinely differ (a 1920x1080 target takes a 2048x1280 grid), so
trail_grid_size scaling both axes by one factor at the cap is about keeping
the field’s sampling near-isotropic, not about the shape on screen.
Re-exports§
pub use family::AttractorFamily;pub use family::Basis;
Modules§
- family
- The attractor families and their projection bases — the ODE/map math, GPU-free (Plan 0061 Phase 6).
- ifs
- Iterated function systems: the
attractorscene’s fifth family (ADR-0075, Plan 0062). - resources
- The attractor’s GPU resources: the three uniform blocks, the three resource holders, and their bind-group helpers (Plan 0061 Phase 6).
Structs§
- Attractor
Scene - GPU compute-particle strange-attractor scene (ADR-0015). A storage buffer of
particles is stepped through the De Jong map by a compute shader each frame,
drawn as additive point-sprites into a fading trail field, and composited to
the surface. Every knob is an ADR-0002 layer-2 named parameter — the attractor
coefficients (
a,b,c,d), the look scalars (size,hue,fade), and a beat-drivenreseed— so a preset binds them to the audio bands and beat.
Constants§
- MIN_
PARTICLE_ DENSITY - The smallest
[particles] densitya preset may ask for (ADR-0069). - PARAMS
- Parameter vocabulary — see
fragment_field::PARAMS. Keep in sync withset_parambelow.
Functions§
- deposit_
scale - Per-particle weight of the additive deposit, so the total light laid into the accumulation each frame is invariant to the particle count (ADR-0065).
- roster_
len - How many entries a family’s roster holds — what
[particles] tuple_tois validated against at load (ADR-0093). - trail_
grid_ size - The trail accumulation grid for a render target of
widthxheight— this scene’s cap and step over the one shared policy (grid::grid_size).