How GLSL textureGather Samples Four Texels

This article provides a technical overview of the textureGather function in GLSL, detailing how the GPU extracts four neighboring texels simultaneously in a single texture lookup. It covers the underlying hardware addressing mechanics, the specific channel selection process, the exact ordering of the returned four-component vector, and the primary rendering scenarios where this instruction delivers optimal performance over standard texture fetches.

The Mechanism Behind textureGather

In traditional texture mapping, the GLSL texture() function performs bilinear interpolation across four adjacent texels to return a single blended color vector. Conversely, textureGather bypasses the fixed-function interpolation hardware. Instead, it directly retrieves the four raw texel values that would have contributed to that bilinear footprint and returns them simultaneously inside a single vec4.

When a 2D texture coordinate \((u, v)\) is passed to textureGather, the GPU converts the normalized coordinates into absolute texel-space coordinates by multiplying them by the texture dimensions and subtracting \(0.5\). The base texel index \((i, j)\) is computed by flooring these continuous coordinates:

\[i = \lfloor u \times \text{width} - 0.5 \rfloor\] \[j = \lfloor v \times \text{height} - 0.5 \rfloor\]

The four texels making up the \(2 \times 2\) sampling footprint are defined by the coordinate pairs:

  • Bottom-left: \((i, j)\)
  • Bottom-right: \((i + 1, j)\)
  • Top-right: \((i + 1, j + 1)\)
  • Top-left: \((i, j + 1)\)

Component Selection

Because a standard GLSL return value is limited to a four-component vector (vec4), textureGather cannot return full RGBA data for all four texels simultaneously. Instead, it extracts one designated color component from all four texels.

The component sampled is determined by an optional integer parameter comp:

  • 0: Red channel (default if omitted)
  • 1: Green channel
  • 2: Blue channel
  • 3: Alpha channel

For depth textures, textureGather automatically samples the depth component.

Texel Layout in the Returned Vector

The four harvested values are packed into the destination vec4 in a counter-clockwise order starting from the upper-left texel relative to the coordinate origin. The OpenGL and GLSL specifications define the component mapping as follows:

  • .x component: Texel at \((i, j + 1)\) [Top-Left]
  • .y component: Texel at \((i + 1, j + 1)\) [Top-Right]
  • .z component: Texel at \((i + 1, j)\) [Bottom-Right]
  • .w component: Texel at \((i, j)\) [Bottom-Left]

This specific mapping allows shader developers to know the spatial orientation of each texel without performing individual coordinate offsets.

Practical Applications and Efficiency

Sampling four texels in a single instruction reduces texture cache pressure and minimizes memory bandwidth bottlenecks. Rather than issuing four separate texelFetch or point-sampled texture calls, the GPU issues one memory transaction to fetch the quad footprint.

Key use cases include:

  • Percentage-Closer Filtering (PCF): In shadow mapping, textureGather allows testing four depth samples against the light-space depth in parallel, followed by custom weighting in shader logic.
  • Custom Bilinear and Bicubic Filtering: Shaders requiring manual interpolation weights (such as categorical textures or normal maps where standard hardware blending corrupts mathematical correctness) can reconstruct filters manually using fractional coordinate weights.
  • Screen-Space Ambient Occlusion (SSAO) and Edge Detection: Depth buffer discontinuities and surface normal edges can be analyzed rapidly across a \(2 \times 2\) neighborhood without multiple fetch instructions.