How to Retrieve Texels Using GLSL imageLoad
The imageLoad function in GLSL allows shaders to read
raw, unformatted texel data directly from specific coordinates within an
image object without hardware filtering. This article explains the
mechanics of how imageLoad operates, how it translates
integer coordinates into memory addresses, handles data format
conversions, and how its operation fundamentally differs from
conventional texture sampling.
The Mechanics of
imageLoad
Unlike the standard texture() family of functions, which
rely on texture samplers, normalized floating-point coordinates
[0.0, 1.0], and fixed-function filtering hardware (such as
bilinear or trilinear interpolation), imageLoad interacts
directly with image units bound to OpenGL textures or texture
buffers.
The function operates through several distinct steps:
Discrete Coordinate Addressing:
imageLoadtakes an image variable (e.g.,image2D,iimage3D,uimage2DArray) and an integer coordinate vector (ivec2,ivec3, etc.). Because the coordinates are discrete integers, they correspond directly to texel indices rather than continuous spatial positions. The coordinateivec2(0, 0)points explicitly to the first texel at the base of the specified mipmap level of the bound texture.Memory Address Calculation:
The GPU calculates the exact memory offset for the target texel based on the bound texture's internal layout, stride, dimensions, and the supplied coordinates: \[\text{Offset} = (y \times \text{Stride}) + (x \times \text{BytesPerTexel})\] Because this bypasses traditional sampler state pipelines, no derivative calculations, mipmap level selections, or neighbor blending occurs.Format Unpacking and Conversion:
Images in GLSL require an explicit format qualifier in the shader layout (for example,layout(rgba32f)orlayout(r32ui)). WhenimageLoadreads the raw bytes from memory, the hardware unpacks the data into a four-component vector matching the image prefix:- Floating-point images (
image*) returnvec4. - Signed integer images (
iimage*) returnivec4. - Unsigned integer images (
uimage*) returnuvec4.
If the internal texture format has fewer than four channels (such as
r32f), the missing channels are filled with default values: \((0, 0, 1)\) for RGB and alpha respectively, resulting invec4(R, 0.0, 0.0, 1.0).- Floating-point images (
Out-of-Bounds Handling:
If the integer coordinates provided toimageLoadfall outside the dimensions of the image, the operation is safe from application crashes, but the returned value depends on driver implementation and context flags. If robustness extensions are active, out-of-bounds reads safely return a vector of zeros (vec4(0.0)). Otherwise, the return value is undefined.
Example Syntax
#version 450 core
// Binding the image with an explicit format layout
layout(binding = 0, rgba32f) readonly uniform image2D uInputImage;
void main() {
// Define the exact texel coordinate to read
ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy);
// Retrieve the unfilitered texel directly from memory
vec4 texel = imageLoad(uInputImage, texelCoord);
// texel now contains the exact data stored at (texelCoord.x, texelCoord.y)
}Key Differences from Standard Sampling
- No Filtering:
imageLoadperforms a direct memory fetch; it cannot perform linear or anisotropic filtering. - No Normalized Coordinates: Coordinates must strictly match the texel grid dimensions.
- Coherency and Synchronization: Unlike read-only
samplers,
imageLoadcan read data that has been modified within the same pass byimageStore, provided memory barriers (such asmemoryBarrierImage()) are properly deployed.