Contents

A signed distance field (SDF) assigns to every point $\mathbf{x}$ in space its signed distance to the nearest surface: negative inside, zero on the surface, positive outside. SDFs enable smooth boolean operations, offsetting, and collision proximity queries without explicit mesh representation.


Definition and properties

For a shape $\Omega$ with boundary $\partial\Omega$:

\[d(\mathbf{x}) = \begin{cases} -\min_{\mathbf{p}\in\partial\Omega}\|\mathbf{x}-\mathbf{p}\| & \text{if } \mathbf{x} \in \Omega \\ +\min_{\mathbf{p}\in\partial\Omega}\|\mathbf{x}-\mathbf{p}\| & \text{if } \mathbf{x} \notin \Omega \end{cases} \tag{1}\]
An SDF satisfies the Eikonal equation almost everywhere: $ \nabla d = 1$.

Primitive SDFs

Circle (radius $r$, center $\mathbf{c}$):

\[d_{\rm circle}(\mathbf{x}) = \|\mathbf{x} - \mathbf{c}\| - r \tag{2}\]

Axis-aligned rectangle (half-extents $\mathbf{b} = (b_x, b_y)$, centered at origin):

\[d_{\rm rect}(\mathbf{x}) = \|\max(\mathbf{q}, 0)\| + \min(\max(q_x, q_y),\, 0), \qquad \mathbf{q} = |\mathbf{x}| - \mathbf{b} \tag{3}\]

Line segment (endpoints $\mathbf{a}$, $\mathbf{b}$):

\[d_{\rm seg}(\mathbf{x}) = \left\|\mathbf{x} - \mathbf{a} - \mathrm{clamp}\!\left(\frac{(\mathbf{x}-\mathbf{a})\cdot(\mathbf{b}-\mathbf{a})}{\|\mathbf{b}-\mathbf{a}\|^2},\, 0,\, 1\right)(\mathbf{b}-\mathbf{a})\right\| \tag{4}\]

Boolean operations and smooth blend

Union, intersection, subtraction via min/max:

\[d_{\rm union} = \min(d_1, d_2), \qquad d_{\rm intersect} = \max(d_1, d_2), \qquad d_{\rm subtract} = \max(d_1, -d_2) \tag{5}\]

Smooth union (Quilez polynomial smooth minimum; $k$ controls blend radius):

\[{\rm smin}(a, b, k) = \min(a, b) - \frac{1}{4k}\left[\max(k - |a-b|,\, 0)\right]^2 \tag{6}\]

Interactive: 2D SDF contour plot

Select a scene and adjust the blend radius. The heatmap shows $d(\mathbf{x})$ over $[-3,3]^2$; the thick black contour is the shape boundary $d=0$.


Python

import numpy as np
import matplotlib.pyplot as plt

def sdf_circle(x, y, cx=0, cy=0, r=1.0):
    return np.sqrt((x - cx)**2 + (y - cy)**2) - r

def sdf_rect(x, y, bx=1.0, by=0.5):
    qx = np.abs(x) - bx
    qy = np.abs(y) - by
    return (np.sqrt(np.maximum(qx, 0)**2 + np.maximum(qy, 0)**2)
            + np.minimum(np.maximum(qx, qy), 0))

def smin(a, b, k=0.3):
    h = np.maximum(k - np.abs(a - b), 0) / k
    return np.minimum(a, b) - h**2 * k / 4

# Evaluate on grid
N = 200
x = np.linspace(-3, 3, N)
y = np.linspace(-3, 3, N)
X, Y = np.meshgrid(x, y)

d = smin(sdf_circle(X, Y, -0.5, 0, 0.9), sdf_rect(X + 0.3, Y, 0.8, 0.5))

plt.figure(figsize=(5, 5))
plt.contourf(X, Y, d, levels=50, cmap='RdBu_r', vmin=-2, vmax=2)
plt.contour(X, Y, d, levels=[0], colors='k', linewidths=2)
plt.axis('equal')
plt.colorbar(label='d(x)')
plt.title('Smooth union SDF')
plt.show()

References

Hart, J. C. (1996). Sphere tracing: A geometric method for the antialiased ray tracing of implicit surfaces. The Visual Computer, 12(10), 527–545.

Quilez, I. (various). Distance functions. Retrieved from https://iquilezles.org/articles/distfunctions2d/

Osher, S. & Sethian, J. A. (1988). Fronts propagating with curvature-dependent speed. Journal of Computational Physics, 79(1), 12–49.

SDFs compose naturally: any boolean or blend operation remains a single distance evaluation per point.