Abelian Sandpile needs a newer GPU pipeline

This sim runs the sandpile rule entirely in a WebGL2 shader with floating-point framebuffers (EXT_color_buffer_float), which this browser doesn't expose. Try a recent Chrome, Firefox, or Safari.

Abelian Sandpile
preset
drive rate
relax speed240/s
brush
brush radius8px

Abelian Sandpile

Every cell on the grid holds a whole number of sand grains.

A cell with more than 3 grains is unstable: it topples, giving one grain to each of its four neighbors and losing four itself —

$$ z_i \to z_i - 4, \qquad z_j \to z_j + 1 \ \text{ for each neighbor } j $$

0
0
4
0
0
1
1
0
1
1

One cell topples: it hits 4, drops to 0, and each of its four neighbors (not the diagonals) gains a single grain. If that pushes a neighbor past 3, it topples next.

A single toppled cell can push a neighbor over the edge, which topples in turn, which can push its neighbors over — a cascade that ends only once every cell in the grid is back at 3 grains or fewer. That cascade is the avalanche.

Toppling is applied to every unstable cell simultaneously, once per pass — exactly the kind of local, parallel update a fragment shader is built for.

Each pixel reads its own grain count and its four neighbors' from a floating-point texture and writes the next state; two textures ping-pong back and forth so an avalanche of any size unfolds as a rapid series of GPU passes, with no simulation code running on the CPU at all.

A stable pile (every cell ≤ 3) never topples on its own, so something has to keep disturbing it — the classic sandpile experiment does this by dropping grains in at random, forever.

Each cell here is one screen pixel, so a single dropped grain is invisible against millions of them. The drive rate instead scatters a batch of grains across random cells every simulation step — the ÷2/×2 buttons trade off between "many grains every step" and "one grain every few steps."

You can disturb it on purpose too: click or drag anywhere to pour grains at the cursor.

Brush sets how many grains land per step while held down, and brush radius spreads them over an area instead of a single point.

Single pile — the default: an empty grid with one enormous pile at the center, relaxed at full speed with no further driving, so you watch one avalanche spread outward from a point and freeze into the strangely intricate, often fractal-looking terrain that gives self-organized criticality its name.

Random piles — the same idea, but with fifteen piles scattered at random instead of one, so their avalanches spread and collide unpredictably.

Two piles — two piles placed so their avalanches collide.

Full, with drip — every cell starts sitting exactly at the critical value, so each dropped grain sets off a cascade immediately, with nothing needing to build up first.

Empty, draw your own — a blank grid with no drive at all, just for drawing with the brush.