Backdrops · effect

MarbledPaper

Ink floated on size, dropped and then raked, the way marbled endpapers are made.

ambient, watch the comb draw through

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

paper #fbfaf4

css colour

The size in the tray, and what shows wherever no ink reached. Match it to the page behind or the margins read as a panel.

ink #36362f

css colour

The main ink. Roughly two thirds of the drops are this, or this thinned toward the paper, which is what a second pass of one colour looks like once the first has spread.

accent #c44400

css colour

The second ink, on roughly a third of the drops.

drops 44

1 to 72

How many drops go into the tray. Each one pushes every earlier one outward, so this sets the density of the rings rather than just the amount of ink.

scale 1

0.2 to 4

How large the pattern reads. Higher zooms in on fewer, bigger shapes; lower pulls back and shows more of the tray, down to the paper margin round the edge of the ink.

spread 0.95

0.1 to 2

How far the drops are scattered. Low stacks them into a single rosette, which is the stone pattern; high covers the tray.

size 0.17

0.05 to 0.8

How big each drop is before anything pushes it. The ink conserves area, so the patch it finally covers is the sum of the drop areas: halving this and quadrupling the count gives the same coverage at four times the detail, which is the knob you actually want.

rake 0.25

0 to 0.6

How far the comb pulls the ink across. Zero leaves the drops as plain rings, which is a stone marble and a perfectly good thing to stop at.

comb 9

0.5 to 30

Teeth per unit across the comb. Higher is a finer comb and a tighter zigzag.

swirl 0.12

0 to 0.4

A second comb drawn at right angles to the first. Two passes crossed is how a gel-git pattern is made; leave it at zero for a single-direction nonpareil.

grain 0.5

0 to 1

Paper tooth over the whole thing.

period 12

2 to 120

Seconds for one pass of the comb. Both combs run whole multiples of the same angle, so the pattern returns to exactly where it started and the loop is seamless. Behind content, raise it.

What it needs

Dependencies
None at all
Browser
WEBGL2
Frame budget
~2 ms · 1 context
Pinned to
v0.8.0
  • Every marbling operation has a closed-form inverse, so each pixel runs the session backwards instead of the tray being simulated forwards. One pass, no render targets, no feedback
  • The drop loop runs backwards and stops at the first drop that contains the point, so raising the count costs much less than it looks like it should
  • One WebGL2 context, one full-screen triangle, no buffers and no attributes
  • Measured 0.42ms at one drop and 0.64ms at seventy-two, at 1440 by 900 on an RTX 3080, timed with a readPixels sync because without one you are timing the dispatch rather than the shader
  • Cost rises with the drop count but far less than linearly: the loop breaks the moment a drop claims the point, so most pixels walk only the last few. The pixels that walk the whole list are the paper margins
  • One inverse-drop per step, which is a dot product and a square root. Nothing is uploaded per frame and only uniforms change