How GLSL equal_spacing Subdivides Edges
This article provides an overview of the equal_spacing
layout qualifier used in OpenGL Shading Language (GLSL) tessellation
shaders. It covers the mathematical mechanics behind edge subdivision,
how floating-point tessellation levels are clamped and rounded, how
normalized parameter coordinates are assigned across segments, and the
visual implications of selecting this spacing mode over fractional
alternatives.
In GLSL, the primitive generation stage handles tessellation based on
parameters declared in the Tessellation Evaluation Shader (TES). When
you specify the equal_spacing input layout qualifier, you
instruct the tessellation primitive generator to divide patch edges into
segments of uniform length based on discrete integer subdivisions.
Floating-Point Clamping and Rounding
Tessellation control shaders output floating-point values for outer
and inner tessellation levels (gl_TessLevelOuter and
gl_TessLevelInner). When equal_spacing is
active, the primitive generator processes these floating-point values
using the following sequence:
- Clamping: The tessellation level is clamped to the
hardware-supported range, bounded below by \(1.0\) and above by the
implementation-dependent limit (
gl_MaxTessGenLevel). - Rounding Up: The clamped floating-point value is rounded up to the nearest integer: \[n = \lceil \text{clamp}(\text{level}, 1.0, \text{max\_level}) \rceil\]
Because the value is rounded up, any non-integer value strictly greater than an integer \(k\) immediately snaps to \(k + 1\). For example, an outer tessellation level of \(3.01\) will round up to \(4\), resulting in four segments.
Edge Subdivision Mechanics
Once the integer segment count \(n\) is resolved, the primitive generator divides the edge within the normalized parameter domain \([0.0, 1.0]\). The edge is split into exactly \(n\) segments of equal length:
- Each segment has an identical parametric length of \(\Delta t = \frac{1.0}{n}\).
- The vertices along the edge are generated at normalized parametric coordinates: \[t_i = \frac{i}{n} \quad \text{for } i \in \{0, 1, \dots, n\}\]
These coordinates are used to produce domain coordinates
(gl_TessCoord), which the Tessellation Evaluation Shader
uses to interpolate surface positions, normals, and texture
coordinates.
Characteristics and Trade-offs
The defining property of equal_spacing is strict
geometric uniformity across an individual edge. Unlike
fractional_even_spacing or
fractional_odd_spacing, which introduce two smaller
segments that smoothly grow or shrink as tessellation levels change,
equal_spacing guarantees that every single segment on a
given edge has the exact same parametric size.
The trade-off of this uniform distribution is visual "popping." When
tessellation levels vary dynamically—such as during continuous Level of
Detail (LOD) transitions based on camera distance—the number of segments
jumps abruptly at each integer boundary, causing noticeable vertex
snapping. As a result, equal_spacing is best suited for
static tessellation factors or applications where strictly uniform
polygon sizing is preferred over smooth LOD blending.