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 variablepbetween 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 variablepbetween 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.
- Span in X and Y: If
prepresents 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. - Bounding the Change: By summing these absolute
differences,
fwidth(p)produces a scalar value that approximates the maximum span or extent ofpenclosed 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.