Signed Distance Fields: 2D Shape Modeling, Composition, and Normals


Signed distance fields (SDFs) are functions that describe geometry by answering one question at every point in space: how far is the nearest surface? Instead of storing triangles or curve segments directly, you store a function and evaluate it wherever you need information. That makes SDFs a strong fit for procedural graphics, where shapes are often created, combined, and animated mathematically.

An SDF returns a signed scalar value d(p)d(\mathbf{p}) at position p\mathbf{p}:

  • positive outside the shape
  • zero on the surface
  • negative inside the shape

The absolute value d(p)|d(\mathbf{p})| is the shortest distance to the boundary. The sign tells which side of the boundary you are on. Those two properties give you both location and orientation information from one function family.

Sign, Magnitude, and Distance Contours

The most useful first intuition is that every point has both a side label (inside/outside) and a distance magnitude. If d(p)=0.12d(\mathbf{p}) = -0.12, the point is 0.12 units inside the shape. If d(p)=0.12d(\mathbf{p}) = 0.12, it is 0.12 units outside. If d(p)=0d(\mathbf{p}) = 0, it is on the boundary.

That means one scalar field stores more than a binary mask. It stores layered contour information around the surface:

  • negative-distance contours inside the shape
  • the zero contour on the shape boundary
  • positive-distance contours outside the shape

SDF Sign and Distance Contours

Inspect sign, magnitude, and nearest-surface distance for a circle or box field.

In the explorer, the sample point readout shows the signed value, absolute distance, and classification. The green segment is the shortest path to the boundary. When you switch between circle and box, the sign contract stays the same even though the geometry changes. That consistency is what makes SDF tooling reusable across many primitive types.

This local distance interpretation is also why SDFs connect naturally to collision margins, adaptive level sets, and distance-based material effects. The same field can drive both shape logic and visual logic.

Primitive 2D SDF Formulas

SDF work starts with primitive formulas. In 2D, many useful shapes have compact expressions:

  • circle with center c\mathbf{c} and radius rr:
    d(p)=pcrd(\mathbf{p}) = \|\mathbf{p}-\mathbf{c}\| - r
  • half-space (line side) with normal n\mathbf{n} and offset hh:
    d(p)=pnhd(\mathbf{p}) = \mathbf{p}\cdot\mathbf{n} - h
  • axis-aligned box with half-size b\mathbf{b} (compact form): combine outside distance and inside offset from clamped coordinates

The circle formula is usually the first one to memorize because it makes the meaning of sign explicit. Outside the circle, distance to center is larger than rr, so the value is positive. On the boundary, it is exactly zero. Inside, it is negative by how deep the point is.

For boxes and other polygons, formulas are slightly longer, but the same semantic contract should hold: accurate sign and conservative distance. If a function loses that contract, later operations still may look plausible but become less reliable for stepping and normals.

Scene Composition with Min and Max

A single SDF primitive is rarely enough. Most scenes are built by combining several fields. The standard boolean-like composition operators are:

  • union: min(a, b)
  • intersection: max(a, b)
  • subtraction (A minus B): max(a, -b)

The union case is the most important starting point. At any sample point, the closest surface controls the combined field value, so the minimum distance is the correct result.

SDF Boolean Composition

Combine two primitive fields with union, intersection, or subtraction and inspect the resulting distance.

In the composer, dashed outlines show the two source fields (A and B) and the colored region shows the final composed field. Move shape B and switch operations to see how the zero contour and interior region update. The readout shows dA, dB, and dScene at the sample point, which makes the composition rule concrete instead of abstract.

For example, in subtraction mode max(dA, -dB), points that are inside B flip sign contribution and carve space out of A. This is exactly how holes, cutouts, and negative-space forms are built in constructive SDF modeling.

This is also the main reason SDF scene code can stay compact. A whole scene graph can collapse into one function that returns one scalar. You can later evaluate that function for rendering, collision checks, masking, and effects, all with the same interface.

Smooth Composition and Shape Design

Hard min and max produce sharp CSG boundaries. For many visual styles, that is exactly what you want. For organic transitions, smooth variants are common. One popular option is smooth minimum (smin) with parameter kk:

h=clamp(0.5+0.5bak,0,1),smin(a,b,k)=mix(b,a,h)kh(1h)h = \mathrm{clamp}\left(0.5 + 0.5\frac{b-a}{k}, 0, 1\right), \quad \mathrm{smin}(a,b,k) = \mathrm{mix}(b,a,h) - k h(1-h)

As kk increases, the blend region widens. As k0k \to 0, behavior approaches hard min. The same idea extends to smooth subtraction and smooth intersection variants.

Hard Union vs Smooth Union

Compare zero contours for hard min and smooth min while adjusting blend width and shape spacing.

The comparison view shows the same two circles in two fields:

  • left: hard union (min)
  • right: smooth union (smin)

At the sample point, you can compare dHard and dSmooth directly. Near the seam between primitives, the smooth field usually becomes slightly more negative than hard min, creating a rounded bridge instead of a sharp join.

Smooth composition is powerful, but it changes local curvature and sometimes field quality. If your pipeline depends on strict distance guarantees for long ray steps, aggressive smoothing can require tighter thresholds or more conservative step logic.

Domain Transforms and Repetition

Another major SDF strength is domain transformation. Instead of changing the shape function itself, you transform input coordinates before evaluation:

  1. Translation: evaluate at pt\mathbf{p} - \mathbf{t}
  2. Rotation: evaluate at R1pR^{-1}\mathbf{p}
  3. Scale: evaluate at p/s\mathbf{p}/s and rescale distance by ss
  4. Repetition: fold coordinates with mod to tile features

These transformations let one primitive definition create many instances. For example, a single circle SDF can become a grid of circles by periodic coordinate folding. This is one reason SDFs are common in shader-based procedural scenes where concise scene definitions are important.

Domain operations also combine naturally with noise modulation. You can use value, Perlin, and fractal noise to perturb coordinates or distances for rocky, molten, or cloud-like surfaces while keeping a function-first modeling workflow.

Surface Normals from the SDF Gradient

An SDF gives more than distance to a hit point. Its gradient points in the direction of fastest distance increase, which corresponds to an outward surface normal near the boundary. In practice, gradients are estimated with finite differences:

d(p)[d(p+εx)d(pεx)d(p+εy)d(pεy)]\nabla d(\mathbf{p}) \approx \begin{bmatrix} d(\mathbf{p}+\varepsilon_x)-d(\mathbf{p}-\varepsilon_x) \\ d(\mathbf{p}+\varepsilon_y)-d(\mathbf{p}-\varepsilon_y) \end{bmatrix}

Then normalize that vector before lighting calculations.

This process is central in field rendering because there is no explicit mesh normal buffer. The same SDF used to locate the surface is also used to estimate orientation for diffuse and specular lighting, reflections, or ambient effects.

Practical Limits and Quality Controls

SDF workflows are simple conceptually, but practical quality depends on several controls:

  1. Hit threshold (epsilon): too large can cause inflated surfaces; too small can cause extra steps and noise.
  2. Step limit: protects against worst-case rays and non-converging estimators.
  3. Max distance: caps work for rays that never hit.
  4. Field quality: exact distance fields allow stronger guarantees than loose distance estimators.

A frequent mistake is to assume any scalar field can be marched like an exact SDF. Distance estimators can still work, but step safety is only as good as estimator conservativeness. When the field underestimates distance, you may overshoot thin features or create missing fragments.

Another common issue is numerical instability around sharp CSG edges and tiny features. Smaller epsilon helps precision but increases sensitivity to floating-point noise. Often the stable choice is a moderate epsilon plus normal smoothing or material-based shading dampening.

Where SDFs Fit in a Rendering Pipeline

SDFs are best viewed as a geometry representation option, not a universal replacement for meshes. They are excellent when shapes are procedural, deformable, or composition-heavy. Meshes remain strong when you need artist-authored topology, UV workflows, and direct hardware triangle acceleration.

A practical split is:

  • rasterization for most scene geometry
  • SDF evaluation for special effects, implicit objects, text, decals, and procedural volumes

If you want the complete traversal context, ray marching with signed distance fields covers the iterative hit search in detail. For stage-level GPU context, vertex and fragment shaders in the graphics pipeline is useful background.

Summary

Signed distance fields encode shape as a scalar function with two strong guarantees: distance magnitude and inside/outside sign. From that single representation, you can:

  1. march rays with distance-guided safe steps
  2. compose scenes with min and max operators
  3. estimate normals from finite-difference gradients
  4. apply domain transforms to build complex procedural layouts

That combination of compact modeling and reusable evaluation logic is why SDFs remain a core tool in procedural graphics. Once the field contract is clear, many techniques that look advanced become variations of the same loop: evaluate distance, move or shade using that result, repeat.