SDF Infinite Repetition Using Modulo in GLSL

This article explains how to achieve infinite spatial repetition of 3D geometry in GLSL raymarching by modifying coordinate space using the modulo operator. By mapping an infinite coordinate space into a recurring periodic domain, a single Signed Distance Field (SDF) evaluation can render an endless grid of duplicated objects without consuming additional computational memory.

The Principle of Domain Repetition

In raymarching, objects are defined by Signed Distance Functions that take a point \(p\) in space and return the shortest distance to the surface of the geometry. Rather than instantiating multiple objects, spatial repetition manipulates the input coordinates before passing them into the SDF.

When you apply a periodic function like modulo to the coordinate vector, space is effectively folded into repeating cells. The SDF evaluates the folded coordinate as if it were a single instance located at the origin of that local cell, causing the raymarcher to render the shape infinitely along the chosen axes.

Implementing Modulo in GLSL

In GLSL, the built-in mod(x, y) function computes \(x - y \cdot \lfloor x / y \rfloor\). If you directly compute mod(p, c) for a cell size c, the coordinates in each cell range from 0.0 to c. Because standard SDF primitives are centered at the origin (0, 0, 0), placing the domain bounds between 0.0 to c cuts the primitive across the cell boundaries.

To keep the primitive centered within each repeated cell, the domain must be offset so that coordinates range from -c / 2 to +c / 2.

The standard GLSL pattern for symmetric repetition is:

vec3 opRepetition(vec3 p, vec3 spacing) {
    return mod(p + 0.5 * spacing, spacing) - 0.5 * spacing;
}

Breakdown of the Formula:

  1. Offsetting the domain (p + 0.5 * spacing): Shifts space forward by half a cell so that the origin aligns with the center of the modulo interval.
  2. Applying mod(..., spacing): Wraps the coordinates periodically within the interval [0, spacing].
  3. Centering the local coordinate (- 0.5 * spacing): Shifts the coordinate back to the range [-0.5 * spacing, 0.5 * spacing], placing (0, 0, 0) directly in the middle of each repeated volume.

Integrating with an SDF

To render an infinite grid of spheres with a radius of 0.2 spaced 1.0 unit apart, the transformed point is passed directly into the sphere distance function:

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

float map(vec3 p) {
    vec3 spacing = vec3(1.0, 1.0, 1.0);
    vec3 q = opRepetition(p, spacing);
    return sdSphere(q, 0.2);
}

You can selectively repeat across fewer dimensions by applying the operation only to specific components of the vector. For example, modifying only p.xz creates a repeating plane of objects while leaving the vertical y axis unchanged.

Limitations and Edge Cases

While modulo repetition is computationally efficient, it introduces specific constraints:

  • Cell Overlap: If the radius or bounds of the geometry exceed 0.5 * spacing, the shape crosses cell boundaries. This leads to harsh geometric clipping and distance field discontinuities, causing raymarching artifacts.
  • Negative Coordinates: GLSL's mod(x, y) is defined as x - y * floor(x / y), which behaves consistently across negative and positive numbers. However, custom modulo implementations or alternative language ports must ensure negative coordinates wrap continuously through zero without creating an asymmetric seam.
  • Index Tracking: Simple modulo repetition discards the unique ID of each cell. If individual instances require variations in color, rotation, or scale, you must compute the cell index (e.g., using floor((p + 0.5 * spacing) / spacing)) before wrapping the coordinates.