How textureQueryLod Calculates Mipmap LOD in GLSL
The GLSL function textureQueryLod computes the mipmap
level of detail (LOD) that the GPU would use when sampling a texture,
without actually fetching texel data. This article explains how
textureQueryLod calculates this value using screen-space
derivatives, what its two-component return value represents, and how
developers can utilize this information for performance optimization,
custom filtering, and visual debugging.
How textureQueryLod
Operates
When rendering textured geometry, the GPU determines which mipmap
layer to sample by analyzing how rapidly texture coordinates change
across adjacent pixels in screen space. Standard sampling functions like
texture() perform this calculation automatically behind the
scenes.
The textureQueryLod function taps directly into this
pipeline stage. Instead of returning a color vector (vec4),
it performs the derivative math on the supplied texture coordinates and
outputs the computed LOD as a two-component floating-point vector
(vec2). Because it skips memory access and texel filtering,
it executes significantly faster than a full texture fetch.
Mathematical Foundation: Screen-Space Derivatives
To compute the LOD, textureQueryLod evaluates the
partial derivatives of the texture coordinate vector (\(uv\)) with respect to window coordinates
(\(x\) and \(y\)):
- \(\frac{\partial uv}{\partial x}\)
(
dFdx(uv)) - \(\frac{\partial uv}{\partial y}\)
(
dFdy(uv))
These derivatives measure the footprint of a screen pixel mapped into texture space. A larger footprint indicates the surface is distant or viewed at an oblique angle, requiring a higher mipmap level (lower resolution) to prevent aliasing.
The implementation calculates the scale factor \(\rho\) based on the maximum rate of change along the coordinate axes:
\[\rho = \max\left(\sqrt{\left(\frac{\partial u}{\partial x}\right)^2 + \left(\frac{\partial v}{\partial x}\right)^2}, \sqrt{\left(\frac{\partial u}{\partial y}\right)^2 + \left(\frac{\partial v}{\partial y}\right)^2}\right)\]
The ideal, continuous level of detail \(\lambda\) is then calculated using a base-2 logarithm:
\[\lambda = \log_2(\rho)\]
Interpreting the Return Value
The function returns a vec2 containing two distinct
variations of the LOD calculation:
result.x(Accessed / Clamped LOD): This component represents the actual mipmap level that a standard sampling function would target. It takes the raw LOD calculation and applies all sampler parameters, includingGL_TEXTURE_MIN_LOD,GL_TEXTURE_MAX_LOD, and the active texture LOD bias.result.y(Unclamped / Ideal LOD): This component provides the raw, unconstrained geometric LOD derived directly from the screen-space derivatives. It does not factor in sampler clamping limits or LOD biases.
If result.x yields 0.0, the fragment maps
1:1 with the base texture (or is being magnified). Values greater than
0.0 indicate minification and correspond directly to higher
mip levels. Fractional values indicate that the sampler would
interpolate between two adjacent mip levels under trilinear
filtering.
Shader Usage and Syntax
The function requires GLSL 4.00 or the extension
GL_ARB_texture_query_lod. It takes a sampler and the
coordinate as arguments:
#version 450 core
uniform sampler2D u_Texture;
in vec2 v_TexCoord;
out vec4 FragColor;
void main()
{
// Query LOD before sampling
vec2 lod = textureQueryLod(u_Texture, v_TexCoord);
// lod.x contains the clamped/biased LOD
// lod.y contains the raw geometric LOD
// Example: Conditionally branch or optimize based on mip level
if (lod.x > 3.0) {
// Use a cheaper fallback calculation for distant geometry
FragColor = vec4(0.5);
} else {
FragColor = texture(u_Texture, v_TexCoord);
}
}Practical Use Cases
- Dynamic Execution Branching: Shaders can bypass complex procedural routines or expensive normal-map operations on distant fragments where the high-frequency detail would be averaged out by higher mip levels anyway.
- Custom Texture Filtering: Developers writing manual anisotropic or stochastic sampling routines can read the hardware's native LOD calculation to determine how many sample taps to execute.
- Visual Debugging: Assigning
lod.xorlod.ydirectly to fragment color output provides a clear, real-time visualization of mipmap transitions across a 3D scene.