aldus.nexus

Reaction-diffusion nebulas

Paint Gray-Scott chemistry with the mouse and grow spots, stripes and coral, guided by a parameter map.

On a planet
drag to paint, E to erase

Parameter map: feed F against kill k

feed F ↑
kill k →

Every tile is its own little dish, grown live with its own F and k: up the side the feed rises, along the bottom the kill rises. Click anywhere to send those numbers to the dish above, and watch the pattern turn into what the tile shows.

  • dark, lower right V dies out: it is removed faster than it can grow.
  • bright, upper left V wins everywhere, or waves roll on for ever.
  • along the dashed curve the narrow band where spots, stripes, worms and coral live, next to the edge where a steady mix stops existing.

waiting to grow

point at the map

The numbers

coverage and mean Vper 1,000 steps
V across the dishhistogram
blobsseparate patches of V

How it works

Two imaginary chemicals share a dish. U is food that flows in from outside; V eats U to make more of itself, and slowly decays. Both spread out, U twice as fast as V. That is all, and yet it paints leopard spots, fingerprints and coral. The numbers below come from one cell of the dish right now, at …: move the pointer over the dish to pick another. The How it works guide has the short version.

1Two chemicals, two equations

Each cell holds an amount of U and of V between 0 and 1. The reaction U + 2V → 3V turns food into more V, at a rate u·v² because it takes two V to make a third. Fresh U is fed in at rate F, topping the dish back up towards 1, and V is drained at rate F + k.

Diffusion spreads each chemical towards its neighbours. Because U spreads faster than V, a patch of V eats the food around it faster than food can flow back, starves its own edges and stops growing. That short-range boost with long-range starvation is what Alan Turing predicted in 1952 would make stripes and spots in living things.

∂u/∂t = Du ∇²u − uv² + F(1 − u)food: spreads, gets eaten, is fed back inu = …, F = …

∂v/∂t = Dv ∇²v + uv² − (F + k)vDu = 1, Dv = 0.5 cells² per stepv = …, k = …

2The Laplacian on a grid

∇² measures how much a cell differs from its surroundings: positive when the neighbours have more, negative when the cell is a peak. On a grid it becomes a weighted sum of the 3×3 neighbourhood, with weights adding up to zero so a flat field does not change. The corners count for a quarter of the sides, which keeps the spreading nearly round instead of square.

Here are the real V values around the chosen cell, and what the stencil makes of them.

∇²x ≈ −x + 0.2 Σ sides + 0.05 Σ cornersKarl Sims' stencil: −1 at the centre, 0.2 on the four sides, 0.05 on the corners∇²u = …∇²v = …

0.2 × 4 + 0.05 × 4 − 1 = 0the weights balance, so only differences matter

3One step forward

Every cell is updated at once with Euler's method and a time step of 1: add each term to the old value. A step is cheap, so the page takes thousands of them: … per frame at … speed.

The reaction term is the same in both equations with opposite signs: what V gains, U loses.

uv² (reaction)= …

F(1 − u) (feed), (F + k)v (kill)= …, …

u′ = u + Δu, v′ = v + ΔvΔu = … → u′ = …Δv = … → v′ = …

4Why the patterns hug a curve

Leave out diffusion and ask where the mixture can sit still. U = 1, V = 0 always works: no V, nothing happens. Two more steady mixtures exist only when F ≥ 4(F + k)², that is k ≤ √F / 2 − F, the dashed curve on the map. Far to the right of it V can never hold on and dies out. Far to the left the dish settles into one even blend.

The patterns live in a thin band just around that curve, where a steady mix is only barely possible and a little diffusion is enough to tip it into spots or stripes. It is a sharp edge, like the boundary of a fractal, and moving k by 0.002 can change everything.

v* = [F ± √(F² − 4F(F + k)²)] / (2(F + k)), u* = (F + k) / v*the extra steady mixtures…

kedge = √F / 2 − Fthe saddle-node curveat F = …: kedge = …, you are …

5Running it on the graphics card

Every cell's update only looks at its 3×3 neighbourhood, so all of them can run at the same time. The state lives in a floating-point texture, U in red and V in green. A fragment shader reads one texture and writes the next step into a second; then the two swap roles, ping-pong, thousands of times a minute. A second shader turns V into colour with a soft glow.

The parameter map is the same shader on one big texture cut into tiles, each tile wrapping round on itself with its own F and k, so hundreds of experiments grow in parallel. Without WebGL2 the page falls back to a smaller grid in plain JavaScript, and the map becomes a sketch. Cells updating by local rules is the idea behind the game of life too, whose Lenia mode is a smooth cousin of this dish; Chaos lab has the same kind of tipping point in time instead of space.

The CPU version is one small function, and the planet forge borrows it to grow these presets as markings on its worlds: On a planet sends the current preset and seed there. Copy link keeps the preset (or your own F and k), palette and seed in the address, and PNG saves the dish as you see it.

two lines of chemistry, run everywhere at once, grow the markings of animals that never had a designer.

Sn+1 = shader(Sn), swaptwo textures, one draw call per step…

cells × steps per secondhow much chemistry this device is doing…