◆ Signed Distance

Level 2 · ○○

An Algebra of Shapes

Prerequisites: Level 1.

Level 1 ended with a heresy: a shape is its distance function. Here is why that matters. Functions return numbers, and numbers have arithmetic — so if shapes are functions, shapes have arithmetic too. This level builds that algebra: three boolean operations that cost one comparison each, a blend that melts geometry like wax, and a family of tricks that conjure infinite copies for free.

min, max, and the algebra of solids

Suppose shape A has field a(p)a(p) and shape B has field b(p)b(p), both signed the usual way: negative inside. What is the field of A-or-B— the union? Stand at any point: you are as close to the union as you are to whichever shape is nearer. And if either field says “inside” (negative), you are inside the union. Both facts at once:

union=min(a,b)intersection=max(a,b)subtraction=max(a,b)\text{union} = \min(a, b) \qquad \text{intersection} = \max(a, b) \qquad \text{subtraction} = \max(-a, b)

Intersection is the mirror image: you must be inside both, so the larger (least inside) value rules. Subtraction is intersection with the complementof A — and negating a signed distance field flips inside and outside, so A's complement is simply a-a. Three set operations from two comparisons and a minus sign:

The boolean workbench
Drag either shape. The ghost lines are the original boundaries; the bright line is the combined shape. Overlap them and watch the field rearrange itself.

One honest footnote, because this site promised honesty: min gives the true distance everywhere outside the union exact, but inside an overlap it can report a distance to a boundary that no longer exists (it got swallowed by the other shape). Intersection and subtraction inherit the same caveat bound. The values are never too large in magnitude — they remain safe bounds — which, as Level 3 will show, is the only property the renderer actually needs.

The smooth minimum — where it starts to feel alive

min has a personality flaw: it is decisive. At every point one shape wins outright, so where the winners change, the combined surface keeps a hard crease. But nothing forces us to be decisive. Near the crossover — wherever aa and bb are within kk of each other — we can let the two fields negotiate:

h=clamp ⁣(12+ba2k,  0,  1),smin(a,b,k)=mix(b,a,h)kh(1h)h = \operatorname{clamp}\!\Big(\tfrac{1}{2} + \tfrac{b - a}{2k},\; 0,\; 1\Big), \qquad \operatorname{smin}(a, b, k) = \operatorname{mix}(b, a, h) - k\,h\,(1 - h)

That is the library's opSmoothUnion bound, written exactly as it ships (mix(b, a, h) is the linear blend b(1h)+ahb\,(1-h) + a\,h). Far from the crossover, hh clamps to 0 or 1 and you get plain min back. Near it, the blend term kh(1h)-k\,h\,(1-h) bulges the field outward, and the crease becomes a fillet. Drag the slider slowly:

The smooth-min morpher
Feel k. At small k the crease survives; raise it and the two shapes negotiate a smooth bridge. Compare mode shows plain min on the left half of the seam.

This one slider is the gateway to generative art, character modeling, and every “blobby” aesthetic you have seen in demoscene work. Two formulas plus kk equals an organism. It is also our first deliberate trade: smoothness for exactness — the Go deeper below has the fine print.

Domain tricks: transform space, not the shape

Every operation so far acted on the fields' outputs. The other half of the algebra acts on the input — the point ppitself — before the field ever sees it. Want the shape somewhere else? Don't move the shape; ask about a moved point. Each trick below is one line applied to pp:

  • Repetition: q = mod(p + 0.5*c, c) - 0.5*c folds all of space into one cell of size cc — the motif repeats forever, for the price of one mod. exact while the shape fits in its cell.
  • Symmetry: q = vec2(abs(q.x), q.y) folds the left half-plane onto the right — instant mirror image.
  • Rotation: q = rot2(angle) * q rotates space backwards, so the shape appears rotated forwards. Distances survive untouched — rotation is rigid.
  • Scaling: d = f(p / s) * s. Shrinking space makes the shape bigger, but it also shrinks the field's values — the trailing * s restores honest distances. Forget it and you break the Lipschitz promise from Level 1.
Transform space, not the shape
Each toggle is one line acting on the point p before the field is asked anything. The motif's formula never changes — space does. Stack them and note that order matters.

Internalize the inversion, because it is the deepest habit of field-thinking: the shape never moves; space is folded, mirrored, and tiled around it. An infinite forest costs the same as one tree.

The mini-studio: your first payoff

You now hold every tool a 2D generative artist needs: a library of exact shapes, a melt knob, and infinite repetition. The studio below composes five random library shapes with opSmoothUnion, optionally tiles them, and lets you export the result — at double resolution, straight from the shader that drew it.

2D generative mini-studio
seed 7
Five library shapes, one seed, one smooth union — your first generative artwork. Randomize until something sings, tile it, and take it home as a PNG.

The field as an oracle

One more gift before the deep dive panels — and it costs nothing you don't already own. Ask the field its value at any point inside a shape. That number is not just a distance: it is the radius of the largest circle that fits there, guaranteed by Level 1's no-surface-within-this-distance promise. Which means the classic generative-art problem of packing shapes snugly — usually solved with collision tests and rejection loops — collapses into a three-step chant: ask the field, place the circle, min it in.

The field as an oracle — circle packing
circles12
No collision tests, no trial-and-error: the field value at a point IS the radius of the largest circle that fits there. Place it, fold it into the field with min, ask again. Flip to the field view and watch the empty-space oracle shrink. Remember this move — Level 3 aims it down a ray.

Two things worth savoring here. First, the algorithm above runs in plain JavaScript on the CPU — no shader computes it, only draws it. Distance fields are mathematics, not GPU technology; plotter artists drive pen-and-paper robots with these same formulas. (This framing — and the packing trick itself — is a staple of the creative-coding world; Piter Pasma's Genuary tutorial is a lovely shader-free introduction.) Second, file away the shape of the move — the field tells you how big a step is safe, you take exactly that step, then ask again. Next level, that exact move, aimed along a ray instead of around a circle, becomes a 3D renderer.

Go deeper: why smin breaks exactness★★

The blend term kh(1h)-k\,h\,(1-h) pushes the field down near crossovers — the combined value becomes smaller than the true distance to the new, smoothed surface. The result is still a valid lower bound (the verifier checks min(a,b)k/4sminmin(a,b)\min(a,b) - k/4 \le \operatorname{smin} \le \min(a,b) numerically), but it is no longer exact anywhere near the weld, even outside the shape.

There is a second, subtler casualty: the smoothed field's level sets are no longer parallel to the surface at uniform spacing — look closely at the stripes near a weld in the morpher and you can see them stretch. Tools that assume exactness (uniform-step contouring, some text-rendering tricks) misbehave on smin fields; the sphere tracer of Level 3 merely slows down.

Go deeper: polynomial vs exponential smin★★★

The quadratic formula above is the workhorse: cheap, branchless, and exactly minoutside the blend band. It has siblings (described here for comparison; this site's library ships only the polynomial form). The exponential smooth minimum

smin(a,b,k)=kln ⁣(ea/k+eb/k)\operatorname{smin}(a, b, k) = -k \,\ln\!\big(e^{-a/k} + e^{-b/k}\big)

blends globally — every shape influences every point, however slightly — and is associative: melting A with B then C gives the same field as any other order, which the polynomial version cannot promise. The price is two exp calls and a field that never quite returns to plain min. For interactive blends of a handful of shapes, the polynomial wins; for N-way organic merges (metaballs), the exponential family is the principled choice.

Go deeper: bound fields — what “still works” actually means★★

After this level most of our fields are bounds, not exact distances. It is worth being precise about the contract a bound field keeps:

  • the zero level set is still exactly the surface — smin, min and max only deform values away from zero, they never move where zero sits relative to the blended shape they define;
  • the value's magnitude never exceedsthe true distance to that surface — the “promise of empty space” from Level 1 survives, just more timidly;
  • the sign still says inside/outside, truthfully.

What is lost is only efficiency and uniformity: an algorithm consuming the field must treat the value as a cautious promise, not a measurement. Every renderer in the rest of this site is built to need nothing more.

What you now know

  • Booleans are comparisons: min = union, max = intersection, max(−a, b) = subtraction — exact outside, safe bounds inside overlaps.
  • The smooth minimum trades exactness for a fillet of width kk — the single most seductive idea in field-based art.
  • Space, not shapes, gets transformed: mod repeats, abs mirrors, rotation rigidly turns, and scaling must pay back its * s.
  • Composition + melt + repetition = a generative art studio in a dozen lines of shader.

Everything so far lives in a flat plane — but length(p) − r never asked how many coordinates pp has. Give it three and it answers with a sphere. The only real question is how to see it… and the field itself will tell us how far we can safely march.

Level 3The March Into 3D