autoplay
theme
2026 · v1.0 · Interactive · Generative · Web

Iris

A meditative browser painting instrument: Stable Fluids in WGSL, Kubelka–Munk pigment mixing, and share links that carry a seed and gesture instead of an image.

A sheet of cotton cardstock, and a breath every 15s that lays down pigment whether or not you do. You work it with one pointer.

The paint is finite. When the wells run dry the flow decays, the image sets the way drying paint sets, and what is left is yours.

What it does

A tap drops a charged bead. Four takes, four landings.
Four brushes. A bloom, a line, a broken skip, a split ribbon.
Taps above. Charged holds below, heavier and running together.
The glass rod combs what is already there. It adds nothing.
Tilt the board and the wet paint runs.
A new box sets the old ring; only new strokes take the new paint.

What it makes

Each from its own session and palette.

A magenta and blue painting, a clean ring with long radiating frondsAn olive ring with lilac fronds, and inside it a deep teal ring grown into branching dendritesA dark violet fronded ring with a pale lavender ring blooming inside it
A dark green painting, an open ring of fronded edges on bare paperA wine-coloured fronded ring holding a second ring of ochre and sage laid in a later paletteAn indigo painting flooded to the edges of the sheet, heavily granulated, around a pale open centre
A dense purple ring of pigment with heavily granulated fronded edges, made by the breath alone with no hand-laid marks
150s. No hand at all.

The solver

Stable Fluids, written as WGSL compute passes rather than assembled in a tool:

velocity   advect → forces → divergence → jacobi → projectpigment    advect → material → resolve → film → dry → bake

Four pigment concentrations advect through the same velocity field and are resolved with Kubelka–Munk, so overlapping pigments subtract the way paint does instead of averaging the way pixels do. Blue over yellow makes green.

One frame of a painting shown four times: as the finished picture, as a greyscale pigment density field, as a water field, and as a velocity field
One instant, four ways: picture, pigment density, water, velocity.

Texture acts on the field as it sets. Granulation settles heavy pigment into the paper's tooth, blanching thins a drying wash, the rim darkens as an edge dries.

The same mark at five moments as it dries, the fronded edge settling and darkening at the rim
One mark. Nobody touching it. 25s.

The instability is deliberate. Saffman–Taylor viscous fingering is what makes an edge break into fronds instead of spreading as a disc.

A link carries the session seed and the gesture recorded at 10 Hz, not an image.

The seed reproduces the piece's own chance: every pulse's noise field, every breath's rotation; everything stochastic routes through one seeded generator, because one stray Math.random makes the recording a lie. The recording reproduces yours, interpolated up to frame rate on playback.

What comes back is not the same image and is not meant to be. GPU float is not bit-identical across vendors and the fingering amplifies any divergence, so a link regrows a painting from the same conditions rather than copying one.

A set blue painting with heavily fingered dendritic edges, the words The pigment has set written across it by the piece, and three low-contrast offers debossed along the bottom edge: keep this one, send it on, begin again
The end of a session: keep this one, send it on, or begin again.

Status

498 unit tests and 55 browser specs driving a real GPU, covering the pigment ledger, the drying curve, the replay clock, the seeded generator. Nothing reaches the piece until a test shows it making the effect it was supposed to make.

One test runs the same capture twice, once as fast as the machine will give frames and once with 0.25s thrown away between every one, and requires the two to come out identical. This is what lets the piece be filmed frame by frame on any machine.

Role
Creator. Solver, pigment model, session and replay, interface
Built with
WebGPU · WGSL compute · TypeScript · Web Audio · Vite
From
A TouchDesigner fluid study, rewritten to run in a browser
Source
Private for now.
Tools
WebGPU · WGSL compute · TypeScript · Web Audio · Playwright