Capsule Signed Distance Function Formula in GLSL

This article provides the mathematical foundation and optimized GLSL implementation of a capsule Signed Distance Function (SDF). You will learn how vector projection is used to determine the distance from an arbitrary point in 3D space to a line segment with uniform thickness, making it ideal for raymarching and procedural geometry generation.

Mathematical Concept

A 3D capsule is defined by two endpoints, point \(A\) and point \(B\), along with a radius \(r\). Geometrically, a capsule is a line segment inflated into 3D space by sweeping a sphere of radius \(r\) along the segment.

To compute the signed distance from an arbitrary query point \(P\) to the capsule:

  1. Find the vector representing the segment: \(v = B - A\).
  2. Find the vector from endpoint \(A\) to the sample point: \(u = P - A\).
  3. Project \(u\) onto \(v\) using the dot product to find the normalized scalar projection \(t\): \[t = \frac{u \cdot v}{v \cdot v}\]
  4. Clamp \(t\) between 0.0 and 1.0 to constrain the closest point strictly within the bounds of segment \(AB\): \[h = \text{clamp}(t, 0.0, 1.0)\]
  5. The closest point on the segment to \(P\) is \(A + h \cdot v\). The vector from this closest point to \(P\) simplifies algebraically to \(u - h \cdot v\).
  6. Calculate the Euclidean length of this difference vector and subtract the radius \(r\): \[\text{distance} = \|u - h \cdot v\| - r\]

GLSL Implementation: Arbitrary Capsule

The following GLSL function implements the arbitrary orientation formula using standard vector operations:

float sdCapsule(vec3 p, vec3 a, vec3 b, float r) {
    vec3 pa = p - a;
    vec3 ba = b - a;
    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    return length(pa - ba * h) - r;
}
  • p: The current sampling point in 3D space.
  • a: The starting coordinate of the capsule's internal segment.
  • b: The ending coordinate of the capsule's internal segment.
  • r: The radius of the capsule.

GLSL Implementation: Vertical Axis-Aligned Capsule

When the capsule is aligned along the Y-axis starting at the origin and extending upward to height h, the general formula can be simplified to avoid vector subtractions and dot products:

float sdVerticalCapsule(vec3 p, float h, float r) {
    p.y -= clamp(p.y, 0.0, h);
    return length(p) - r;
}

This simplified form clamps only the Y-component of the position vector, reducing the computational overhead while producing identical visual results for axis-aligned shapes.