Difference Between dFdxCoarse and dFdxFine in GLSL
This article explores the operational differences, visual
characteristics, and performance impacts of coarse derivatives
(dFdxCoarse, dFdyCoarse) versus fine
derivatives (dFdxFine, dFdyFine) in GLSL
fragment shaders. Modern GPUs calculate screen-space derivatives by
processing fragments in \(2 \times 2\)
pixel clusters (quads). Understanding how coarse and fine operations
sample and distribute rates of change across these quads is essential
for optimizing texture filtering, procedural shading, and normal map
generation.
The GPU Quad Execution Model
Modern graphics hardware executes fragment shaders simultaneously in \(2 \times 2\) pixel groups called "quads." To calculate standard screen-space derivatives—the rate of change of a variable relative to screen coordinates—the hardware compares the values of a variable across the fragments within the same quad:
- Top-left: \((x_0, y_0)\)
- Top-right: \((x_1, y_0)\)
- Bottom-left: \((x_0, y_1)\)
- Bottom-right: \((x_1, y_1)\)
The default functions dFdx and dFdy allow
the GPU driver to choose whether to calculate these rates of change with
coarse or fine granularity. Specifying dFdxCoarse or
dFdxFine directly controls how differences are evaluated
across the quad.
How dFdxFine Works
Fine derivatives calculate distinct derivative values for each adjacent horizontal or vertical pair within the \(2 \times 2\) quad.
- Horizontal Calculation (
dFdxFine):- The top-left and top-right pixels calculate \(\Delta x_{\text{top}} = p(x_1, y_0) - p(x_0, y_0)\).
- The bottom-left and bottom-right pixels calculate \(\Delta x_{\text{bottom}} = p(x_1, y_1) - p(x_0, y_1)\).
- Result: The top row of pixels receives the top row's difference, and the bottom row receives the bottom row's difference.
Because distinct rates of change are preserved across the individual
rows and columns of the quad, dFdxFine yields per-fragment
precision.
How dFdxCoarse Works
Coarse derivatives compute a single derivative value for the entire \(2 \times 2\) quad and duplicate it across all four fragments.
- Horizontal Calculation (
dFdxCoarse):- The GPU computes one difference across the quad (typically evaluating only the top row: \(p(x_1, y_0) - p(x_0, y_0)\)).
- This single derivative value is assigned to all four pixels in the quad, ignoring the bottom row's actual rate of change.
- Result: All four fragments in the \(2 \times 2\) cluster share identical derivative results.
Key Differences
| Feature | dFdxCoarse /
dFdyCoarse |
dFdxFine /
dFdyFine |
|---|---|---|
| Precision | Low (uniform across \(2 \times 2\) quad) | High (distinct per row/column) |
| Visual Artifacts | Can cause blocky \(2 \times 2\) pixel artifacts | Smooth, continuous transitions |
| Arithmetic Cost | Minimal (fewer subtraction operations) | Slightly higher ALU instruction count |
| Evaluation Scope | One evaluation broadcast to all 4 pixels | Independent evaluations per row/column |
Practical Use Cases
When to Use Fine Derivatives
Fine derivatives are ideal for high-frequency shading calculations where accuracy is paramount to avoid visual aliasing. Common use cases include:
- Procedural Normal Mapping: Calculating analytical surface normals from depth or noise functions in screen space.
- Raymarching and SDF Rendering: Edge detection and gradient estimation where quad-wide averaging causes noticeable stepping artifacts.
- Anti-Aliasing Functions: Procedural wireframes or
step functions (like
fwidthcombined withsmoothstep) that require sharp, sub-pixel accuracy.
When to Use Coarse Derivatives
Coarse derivatives are useful when derivative precision is secondary to performance or uniformity:
- Texture LOD / Mipmap Selection: Level-of-detail calculations often benefit from uniform derivatives across the quad, preventing adjacent pixels within the same quad from sampling different mip levels.
- Performance-Critical Post-Processing: Shaders with heavy derivative usage that run on mobile or low-power hardware can benefit from reduced register pressure and ALU overhead.