What Is GLSL texelFetch and How Does It Work?

In OpenGL Shading Language (GLSL), standard texture sampling uses normalized floating-point coordinates and applies filtering such as bilinear interpolation or mipmapping to blend pixel data. The texelFetch function alters this workflow by bypassing the sampler hardware, allowing shaders to read exact, unmapped texel values directly from a texture using integer coordinates. This article examines the mechanics of texelFetch, how it circumvents hardware filtering pipelines, its core syntax, and its key applications in modern graphics rendering.

Understanding Standard Sampling vs. Direct Fetching

Standard texture sampling in GLSL is performed using functions like texture(). These functions require normalized floating-point coordinates (ranging from 0.0 to 1.0) and route the texture lookup through the GPU's fixed-function texture filtering hardware. Depending on the texture's configuration parameters (GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER), the GPU blends neighboring texels via nearest-neighbor, bilinear, or trilinear interpolation.

While interpolation is essential for mapping textures onto 3D surfaces smoothly, it modifies raw numerical values. When textures are used for data storage or pixel-precise operations, interpolation introduces unwanted artifacts and inaccuracies.

texelFetch eliminates the filtering stage entirely. It treats a texture as a raw multidimensional array in GPU memory, addressing individual texels via non-normalized integer coordinates.

How texelFetch Bypasses the Filtering Pipeline

The standard texture pipeline involves several stages:

  1. Mapping normalized coordinates \((u, v)\) to texture resolution \((W, H)\).
  2. Calculating level-of-detail (LOD) based on screen-space derivatives.
  3. Fetching adjacent texels across one or two mipmap levels.
  4. Blending fetched values using interpolation weights.

When invoking texelFetch, the GPU skips coordinate conversion, derivative calculation, and blending arithmetic. The integer coordinate maps directly to a discrete memory offset:

\[\text{Offset} = y \times \text{Width} + x\]

Because it bypasses the sampling hardware, texelFetch does not respect wrap modes such as GL_REPEAT or GL_MIRRORED_REPEAT. Requesting coordinates outside the texture dimensions results in undefined behavior or returning zero, depending on the graphics driver and hardware specification.

Syntax and Core Parameters

The function signature for a standard two-dimensional texture lookup is:

gvec4 texelFetch(gsampler2D sampler, ivec2 P, int lod);

Parameter Breakdown

Example Implementation

In a deferred rendering fragment shader, accessing the exact G-buffer data for the current screen pixel is written as:

#version 330 core

uniform sampler2D gPosition;
uniform sampler2D gNormal;

out vec4 FragColor;

void main()
{
    ivec2 pixelCoord = ivec2(gl_FragCoord.xy);
    
    // Read raw data without interpolation
    vec3 position = texelFetch(gPosition, pixelCoord, 0).rgb;
    vec3 normal   = texelFetch(gNormal, pixelCoord, 0).rgb;
    
    // Perform lighting calculations
    FragColor = vec4(position + normal, 1.0);
}

Primary Use Cases in Modern Graphics

Direct texel fetching is standard across several rendering architectures:

1. Deferred Shading and Post-Processing

Deferred renderers output geometric attributes (normals, depth, albedo, specular factors) into multiple render targets known as the G-buffer. When computing lighting in subsequent passes, the fragment shader needs the exact data stored for the corresponding pixel. Using standard sampling could cause color bleeding along geometric edges due to filtering; texelFetch ensures 1:1 pixel-to-texel mapping using gl_FragCoord.xy.

2. General Data Storage (Data Textures)

Textures are frequently used to pass non-visual structured data to shaders, including:

Because matrix components and discrete indices cannot tolerate linear blending, texelFetch preserves the raw numerical integrity of the data.

3. Custom Filtering Algorithms

When implementing specialized filtering techniques—such as custom bicubic interpolation, bilateral blur, or screen-space ambient occlusion (SSAO)—developers often require direct access to neighboring pixels. texelFetch allows shaders to step across pixels using explicit integer offsets (pixelCoord + ivec2(dx, dy)), giving full control over the mathematical weighting directly in code.

4. Multisample Anti-Aliasing (MSAA) Resolves

When working with multisampled textures (sampler2DMS), shaders cannot use standard interpolated sampling. texelFetch provides a specific overload that accepts a sample index parameter, enabling manual resolving and tone-mapping of individual MSAA samples before final output.