Understanding GL_CLAMP_TO_BORDER in GLSL

This article provides an overview of how the GL_CLAMP_TO_BORDER texture wrap mode operates when sampling textures in OpenGL Shading Language (GLSL). It explains the interaction between CPU-side texture parameter configuration, the underlying hardware texture sampling unit, filtering mechanics, and how GLSL shaders transparently handle out-of-bounds coordinates.

How GL_CLAMP_TO_BORDER Works in GLSL

In GLSL, shader code does not require any special functions or conditional statements to handle GL_CLAMP_TO_BORDER. When using standard texture sampling functions—such as texture(), textureLod(), or texelFetch()—the texture hardware handles coordinate evaluation automatically.

When a texture coordinate falls outside the normalized range of [0.0, 1.0], the hardware texture sampling unit detects that the coordinate has exceeded the boundary. Instead of clamping to the outer edge pixels (GL_CLAMP_TO_EDGE) or repeating the pattern (GL_REPEAT), it returns a constant predefined border color.

Specifying the Border Color

The border color is a state configured on the CPU side through the OpenGL API, not inside the GLSL shader itself. It is assigned to a texture object or a sampler object:

float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // RGBA
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

When a sampler in GLSL samples from this texture with coordinates such as vec2(-0.2, 0.5) or vec2(1.5, 1.2), the returned vec4 will be vec4(0.0, 0.0, 0.0, 1.0).

Impact of Texture Filtering

The exact value returned near the edges depends on the minification and magnification filters (GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER):

  • GL_NEAREST: The texture unit chooses the nearest texel. If the sample coordinate maps past the outer boundary of the outermost texel centers, the exact border color is returned immediately.
  • GL_LINEAR: The texture unit linearly interpolates between the edge texels and the border color across a half-texel wide strip along the perimeter. Coordinates near the border smoothly transition into the border color rather than switching abruptly.

Special Texture Types

  • Integer Textures: When using signed or unsigned integer formats (such as isampler2D or usampler2D), glTexParameterIiv or glTexParameterIuiv must be used to define the border color. Passing standard float values will cause undefined behavior or clamping.
  • Depth and Shadow Textures: When depth comparison modes (GL_COMPARE_REF_TO_TEXTURE) are active, the border color's depth component is used in the comparison operation. This is commonly leveraged in shadow mapping to ensure areas outside the shadow map frustum evaluate consistently as either fully in shadow or fully lit.