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:

  1. 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, including GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, and the active texture LOD bias.
  2. 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.x or lod.y directly to fragment color output provides a clear, real-time visualization of mipmap transitions across a 3D scene.