fwidth
Computes the sum of absolute derivatives.
Test fwidth in a live shader
Open the playground, start from a visual preset, and wire fwidth into the fragment stage to see how it behaves with real values.
Open PlaygroundLive Demo
The fwidth function returns the sum of the absolute partial derivatives in x and y, computed as abs(ddx(x)) + abs(ddy(x)). This is useful for anti-aliasing and filter width calculations.
Signature
fwidth :: (T x) -> T {...}
Where T can be float, float2, float3, or float4.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | T | The value to compute filter width for |
Return Value
Returns abs(ddx(x)) + abs(ddy(x)).
Example
pipeline AntialiasedGrid {
@fragment_only
fragment {
// Draw anti-aliased grid lines
float2 uv = input.uv * 10.0; // 10x10 grid
float2 grid = abs(fract(uv) - 0.5);
// Use fwidth for consistent line width regardless of angle
float2 fw = fwidth(uv);
float2 lines = smoothstep(0.5 - fw, 0.5, grid);
float gridPattern = min(lines.x, lines.y);
output.color = float4(float3(gridPattern), 1.0);
}
}Common Use Cases
Anti-Aliased Lines
// Consistent line width
float lineWidth = 0.02;
float lineDist = abs(uv.y - 0.5);
float aa = fwidth(uv.y);
float line = 1.0 - smoothstep(lineWidth - aa, lineWidth + aa, lineDist);SDF Anti-Aliasing
// Smooth SDF edges
float sdf = signedDistance(position);
float edgeWidth = fwidth(sdf) * 0.5;
float shape = 1.0 - smoothstep(-edgeWidth, edgeWidth, sdf);Procedural Textures
// Anti-aliased checkerboard
float2 checker = step(0.5, fract(uv * 4.0));
float pattern = abs(checker.x - checker.y);
float filtered = pattern * (1.0 - fwidth(uv.x * 4.0));Text Rendering
// Distance field text
float dist = sample(sdfFont, uv).r;
float width = fwidth(dist);
float alpha = smoothstep(0.5 - width, 0.5 + width, dist);Wireframe Overlay
// Barycentric wireframe
float3 bary = input.barycentric;
float3 fw = fwidth(bary);
float3 edges = smoothstep(float3(0.0), fw * wireWidth, bary);
float wire = 1.0 - min(min(edges.x, edges.y), edges.z);Why fwidth?
fwidth gives a screen-space measure of how fast a value is changing. This makes it perfect for determining how wide to make anti-aliased transitions—the faster a value changes, the wider the transition should be.
Alternative Calculation
For gradient-based calculations, you might use length(float2(ddx(x), ddy(x))) instead, which gives the Euclidean magnitude rather than the Manhattan distance.
Compiled Output
When compiled to GLSL:
fwidth(x)
When compiled to HLSL:
fwidth(x)
When compiled to SPIR-V:
Uses OpFwidth instruction.
See Also
- ddx - Derivative in x
- ddy - Derivative in y
- smoothstep - Smooth interpolation