Task 5 of 6
Seeds do not have to be dots. Seed the flood with every pixel inside a shape and the finished field answers "how far is the nearest inside pixel?" — which is 0 inside and grows outside. Seed it with every pixel outside and you get the mirror image. Subtract one from the other and the result is a signed distance field: negative inside, zero on the boundary, positive outside.
Ray-Marched Metaballs marches an SDF that is defined analytically
— a sphere is length(p) − r, and the whole scene is a formula. This is the other
half of that story: here you manufacture one from an arbitrary bitmap.
Nothing about a five-pointed star wants to be a formula, and it does not have to be. Two
ladders and a subtraction, and it is marchable, glowable, outlineable — exactly like the
analytic kind.
The bookkeeping is the interesting part. dIn is 0 for every inside pixel and
positive outside; dOut is 0 for every outside pixel and positive inside. So
dIn − dOut is signed automatically, with no test on the mask at all — one of
the two terms is always zero.
seedWhere(mask, want) — seed the cells where
the mask equals want — and combine(dIn, dOut), which returns
dIn − dOut.seedWhere returns the packed id where mask[y][x] === want, else -1want = 1 and once with want = 0, awaiting each laddercombine returns dIn − dOut — negative inside, positive outsideThe same packed id as ever, gated on the mask:
let id = -1;
if (mask[y][x] === want) id = y * this.constants.n + x;
return id;
The want argument is what lets one kernel seed both sides.
ladder() takes any seeded field, so it runs twice unchanged:
const dIn = await distance(await ladder(await seedWhere(mask, 1)));
const dOut = await distance(await ladder(await seedWhere(mask, 0)));
Fourteen passes in total, and every one of them awaited in order.
Inside a pixel of the shape, the nearest inside pixel is itself, so
dIn = 0 and the answer is −dOut. Outside,
dOut = 0 and the answer is +dIn. The subtraction is the whole
sign logic.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.