28

I wanted a big swirling particle cloud following a Lorenz/Thomas attractor. CPU-updating 100k positions per frame in JS was a slideshow. I knew I needed the integration to happen on the GPU but kept getting scenes that computed positions on the CPU anyway.

What worked was explicitly asking for the attractor integration to live in the vertex shader driven by uTime, with only static seed positions uploaded once. Making the trajectory a pure function of (seed, time) means zero per-frame CPU work and it's deterministic.

Any recommended additive-blend settings so the dense core doesn't just clip to solid white?

THE PROMPT
Build a self-contained three.js scene: {COUNT} GPU particles (default 100000) tracing a strange attractor. Performance rules:
- Upload ONLY static per-particle seed attributes once (a seed float + initial offset). No position updates from JS after init.
- Integrate the attractor in the VERTEX shader as a function of `uTime` and the particle seed so the CPU does nothing per frame. Use the Thomas attractor (dx=sin(y)-b*x, etc.) with `uB` uniform; step it a fixed number of iterations in-shader from the seed.
- Render as `Points` with a custom ShaderMaterial; size attenuates with distance, clamped.
- Additive blending (`THREE.AdditiveBlending`, depthWrite:false) with a soft radial falloff in the fragment (discard past radius 0.5) so the cloud glows without hard squares.
- Color particles by their speed (finite-difference two shader steps) mapping slow->cool, fast->warm.
- OrbitControls, DPR capped at 2, and a small GUI for uB and uTime scale.
State your per-frame CPU cost (should be ~0) and how you avoid white-clipping the dense core.
6pure-function-of-(seed,time) trajectories being deterministic is a sneaky bonus, you get free scrubbing and reproducible renders.onepromptwonder 1 month ago
add a comment

1 Answer

21

Integrating the attractor purely from seed+time in the vertex shader is elegant but note it re-runs all N iterations every frame for every particle, so cost scales with iterations*count. For dense clouds keep iterations modest and instead vary the per-particle start time (phase) so the swarm spreads along the trajectory. To beat white-clipping, lower per-particle alpha and lean on additive accumulation, and add a mild tonemap on a post pass.

THE PROMPT
Give each particle a phase: `float t = uTime + seed*uSpread;` and integrate ~60 fixed steps from a shared start. Set fragment alpha ~0.15 with additive blend, then apply an ACES tonemap in a post-process pass so the core rolls off instead of clipping.

Your Answer