PS
Tinkering
Particle Stream

A hundred thousand drifters in a wind they can't see.

Each particle holds a position in a floating-point texture. Every frame, a fragment shader reads the texture, samples a three-dimensional curl-noise field at the particle's location, and writes a new position back. The result is a divergence-free flow — particles swirl without piling up. Then a second material reads the texture in its vertex shader and draws one additive point per pixel. The whole simulation lives on the GPU; the CPU only sets a few uniforms each frame.

Three.js · GPGPU · 100k particles · curl of simplex noise

Move the mouse to push the cloud · click to swirl harder · 50k/100k/200k buttons bottom-right

weekend sketch · Three.js r169 + GPUComputationRenderer

The state lives on the GPU

Each particle is one texel in a 317-by-317 floating-point texture. The fragment shader is the simulation: it reads the texture, computes a new position, writes it to a second texture, then they swap (ping-pong). The CPU never touches a particle, which is why 100k stays at 60fps on a laptop.

Why curl noise

Plain Perlin or simplex noise has divergence — sample it as a velocity field and particles collapse into sinks. The curl operator (∂/∂y of the z-component minus ∂/∂z of the y-component, and cyclic) produces a divergence-free field. Particles drift with the wind but never pile up — the visual texture that defines this aesthetic.

Mouse as a repulsor

Move the cursor and a soft Gaussian repulsor pushes particles outward in 3D. Click and drag and the strength doubles. The mouse position is projected from screen space to the z=0 plane of the simulation, so the depth of the cloud reads correctly under the cursor.

The next step

Same scaffold, different velocity field: swap the curl noise for a set of attractors, or for the gradient of a signed-distance field around a 3D logo, and the same particles will reshape themselves around the new geometry. That's how the Houdini-style aesthetic generalises in the browser.