Signed Distance Fields (SDF)

One function answers, for any point in space, how far the nearest surface is and which side of it you're on. The shape is just where the answer hits zero — and once geometry is a field of numbers, modeling becomes min and max, and the gradient hands you the normal for free.

Core Idea

The picture above is not a drawing of two shapes — it’s a field. Every pixel evaluates one function, f(p), and paints the number that comes back: how far is this point from the nearest surface? Sea means positive (outside), terracotta means negative (inside), and the cream line is where f(p) = 0. That’s the whole definition of a signed distance field: the “shape” is nothing but the zero crossing of a function that has an opinion everywhere — move the cursor across empty space and the readout still answers.

One Number, Two Facts

An ordinary distance is always positive — it only says how far. A signed distance smuggles in a second fact, which side:

distance(a, b)        = |b − a|   // how far — always ≥ 0
signed_distance(a, b) =  b − a    // how far AND which direction

Positive: outside. Negative: inside. Zero: exactly on the skin. That one sign bit is what turns a measurement into geometry — f(p) < 0 is an inside-test, no mesh required. It’s the same move that turns an equation into a region in linear inequalities: x² + y² < r² doesn’t describe a circle’s outline, it describes its interior.

A Shape Is a Formula

For simple shapes the field is exact and tiny:

float sdSphere(vec3 p, float r) { return length(p) - r; }

float sdPlane(vec3 p)           { return p.y; }   // ground at y = 0

float sdBox(vec3 p, vec3 b) {
  vec3 q = abs(p) - b;
  return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}

No vertices, no index buffer — length(p) - r is the sphere, at every resolution, forever. Inigo Quilez’s site (iquilezles.org) catalogs exact fields for dozens of shapes; most production SDF work starts there.

Modeling Is min and max

Because shapes are numbers, combining shapes is arithmetic on those numbers — this is Constructive Solid Geometry, and the hero’s mode buttons are exactly this table:

Operation Formula Meaning
union min(a, b) the nearer surface wins — both shapes
intersection max(a, b) only where both are inside
subtraction max(a, −b) flip b inside-out, keep the overlap — b carved from a

Watch the field when you switch modes, not just the outline: the iso-rings reorganize everywhere at once, because the operation rewrites the answer at every point in space, not just on the boundary. There’s also a soft version — smin(a, b, k) blends two fields so shapes melt together instead of meeting at a seam. That operation, and everything about actually rendering these fields, lives in ray marching.

The Gradient Is the Normal

The field’s value tells you how far the surface is. Its gradient — the direction the value climbs fastest — tells you which way, and at the surface itself that direction is exactly the normal. No stored normals, just four to six extra samples:

vec3 sdfNormal(vec3 p) {
  vec2 e = vec2(0.001, 0.0);
  return normalize(vec3(
    sdf(p + e.xyy) - sdf(p - e.xyy),
    sdf(p + e.yxy) - sdf(p - e.yxy),
    sdf(p + e.yyx) - sdf(p - e.yyx)));
}

Together the two facts are a complete navigation kit: from any point, p − f(p)·∇f walks straight to the nearest surface and lands on the skin. That one line is an SDF collision response (push a penetrating point back out), a shrink-wrap projection, and the reason a marching ray can jump f(p) with a guarantee of hitting nothing — and the recovered normal feeds the same dot-product lighting as any mesh.

Where the Field Shows Up

Connections

A signed distance is the smallest possible geometry kit: one scalar with a sign, promoted from measurement to scene description the moment ray marching starts walking it. The zero contour ties to implicit regions and inequalities; the gradient ties to normals and through them to every lighting model built on the dot product; smooth CSG is field-space interpolation.

Open Questions