How GLSL fwidth Estimates Pixel Footprint

In OpenGL Shading Language (GLSL), the fwidth function provides a fast, hardware-accelerated way to measure how quickly a variable changes across neighboring screen pixels. By combining the screen-space partial derivatives dFdx and dFdy, fwidth estimates the rate of change—or "footprint"—of a value across a single pixel. This article explains the underlying quad-based GPU architecture, the mathematical formula powering fwidth, and how it translates screen coordinates into parameter-space bounds for tasks like anti-aliasing and procedural texturing.

GPU Fragment Quads and Partial Derivatives

GPUs execute fragment shaders concurrently in locked groups of four pixels arranged in a 2x2 grid, known as a quad. Because neighboring fragments within a quad execute in lockstep, the GPU hardware can compute differences in values between adjacent horizontal and vertical pixels:

  • dFdx(p) calculates the difference of variable p between the current fragment and its horizontal neighbor: \(\frac{\partial p}{\partial x} \approx p(x+1, y) - p(x, y)\).
  • dFdy(p) calculates the difference of variable p between the current fragment and its vertical neighbor: \(\frac{\partial p}{\partial y} \approx p(x, y+1) - p(x, y)\).

These functions return the instantaneous rate of change of any given variable p relative to screen coordinates.

The Mathematical Definition of fwidth

The fwidth function evaluates the magnitude of change across the pixel by combining both horizontal and vertical derivatives. In the GLSL specification, fwidth is defined as:

\[\text{fwidth}(p) = |\text{dFdx}(p)| + |\text{dFdy}(p)|\]

Instead of calculating the true Euclidean length (L2 norm) via \(\sqrt{(\text{dFdx}(p))^2 + (\text{dFdy}(p))^2}\), fwidth uses the Manhattan distance (L1 norm). The L1 norm avoids costly square root and multiplication operations, providing a computationally cheap, hardware-friendly approximation of total variation across the pixel area.

Estimating the Pixel Footprint

When mapping values like UV coordinates, distance fields, or world positions to screen pixels, a single screen pixel covers a specific area in that variable's coordinate space. This covered area is referred to as the pixel footprint.

  1. Span in X and Y: If p represents a coordinate (such as a texture coordinate \(u\)), \(|\text{dFdx}(p)|\) represents how much \(u\) changes across one pixel horizontally. Similarly, \(|\text{dFdy}(p)|\) indicates how much \(u\) changes vertically.
  2. Bounding the Change: By summing these absolute differences, fwidth(p) produces a scalar value that approximates the maximum span or extent of p enclosed by the pixel. If the camera is far away or viewing a surface at a grazing angle, the derivatives become large, indicating that the pixel spans a large region of the parameter space. If the camera is close, the derivatives become small, meaning the pixel covers a narrow range.

Practical Use in Anti-Aliasing

The primary use of this footprint estimation is determining filter widths for analytical anti-aliasing. When rendering sharp procedural patterns—such as step functions, stripes, or signed distance fields (SDFs)—rendering without a footprint results in aliasing artifacts.

By passing fwidth into interpolation functions like smoothstep, shaders automatically scale edge transitions to span exactly one or two pixels:

float edge = 0.5;
float width = fwidth(dist);
// Smoothly interpolate across the span of the pixel footprint
float alpha = smoothstep(edge - width, edge + width, dist);

This guarantees that procedural boundaries remain smooth and visually consistent regardless of camera distance, surface tilt, or screen resolution.