The primitive arsenal

Built on his 2D distance functions by Inigo Quilez. Sources for this reference

Almost everything in a 2D field is a handful of primitives combined. Getting them right once matters more than having many, because a primitive that returns the wrong magnitude breaks every effect downstream while still looking fine as a silhouette.

Circle, box, rounded box, capsule. Then triangle, hexagon, arc, pie. Distance bands outside each.

The test is the bands, not the shape

Look at the rings around each primitive. They are evenly spaced and concentric, everywhere, including around corners. That is what a true distance field looks like, and it is the fastest way to check a primitive you did not write yourself.

A common failure: a primitive that gets the sign right and the magnitude wrong. It draws perfectly, because drawing only needs the sign. Then you add a glow and the halo is fat on one side, or you add an outline and it varies in thickness around the shape. The bands show that immediately; the silhouette never will.

The two that people get wrong

The box interior. The correct form has two pieces, and the second is the one that gets dropped:

vec2 d = abs(p) - b;
return length(max(d, 0.0))          // outside: distance to the corner region
     + min(max(d.x, d.y), 0.0);     // inside: the NEGATIVE part

Without that second term the field is zero everywhere inside, which is fine for a silhouette and useless for anything that needs interior distance, including smin, bevels and inner glows.

The arc. Written naively it returns a distance to an infinite ring with an angular test bolted on, which tears at the ends. It needs an explicit fallback to the nearer endpoint when the query is outside the sweep, or the field is discontinuous exactly where the cap is.

Rounding is free

Any shape can be rounded by subtracting a constant, because subtracting from a distance field moves the surface outward by that amount uniformly. So sdRoundBox is not a separate primitive, it is sdBox with a shrunken half-extent and a subtraction. The same trick gives you an inset, a shell (abs(d) - t) and an outline for free.

Rules of thumb

  1. Check a primitive by its distance bands, never by its silhouette.
  2. Inside must be negative and correct in magnitude, not just negative.
  3. Round by subtracting. Do not write a second primitive.
  4. abs(d) - t turns any shape into a shell of thickness 2t.
  5. Prefer the published closed forms over hand-rolled ones. The failure modes are subtle and appear only downstream.

All 61 notes How to use them Credits