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:
- Mapping normalized coordinates \((u, v)\) to texture resolution \((W, H)\).
- Calculating level-of-detail (LOD) based on screen-space derivatives.
- Fetching adjacent texels across one or two mipmap levels.
- 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
sampler: The texture sampler to read from (such assampler2D,isampler2D,usampler2D, orsampler2DMSfor multisampled textures).P: The zero-based integer coordinates of the texel. For a 2D texture with dimensions \(512 \times 512\), valid coordinates range fromivec2(0, 0)toivec2(511, 511).lod: The specific mipmap level to sample. For textures without mipmaps or base-level access, this value is set to0.
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:
- Animation bone matrices
- Lookup tables (LUTs) with non-linear distributions
- Voxel grid definitions
- Particle physics parameters
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.