How Does GLSL Centroid Sampling Fix MSAA Artifacts?
Multisample Anti-Aliasing (MSAA) smooths jagged polygon edges by
evaluating coverage across multiple sub-pixel sample points, but
standard interpolation can inadvertently evaluate fragment shader inputs
outside a primitive's boundary. When standard center-pixel interpolation
extrapolates attribute data beyond a triangle's edge, it triggers severe
visual artifacts such as invalid texture lookups, dark halos, or math
errors. In the OpenGL Shading Language (GLSL), the centroid
interpolation qualifier forces the GPU to evaluate varying attributes
strictly inside the covered area of the polygon, eliminating
out-of-bounds extrapolation while preserving the edge-smoothing benefits
of multisampling.
The Mechanics of Standard Multisampling
In classic MSAA pipelines, color calculation and coverage testing operate on distinct granularities. While a pixel contains several coverage sample points (such as 4x or 8x MSAA), the fragment shader typically runs only once per covered pixel to conserve performance.
By default, GLSL evaluates incoming varying attributes (such as texture coordinates, normals, and colors) at the exact geometric center of the pixel. The GPU then broadcasts this single resulting color to every sample location within that pixel that passed the coverage and depth tests.
Why Standard Center Interpolation Fails at Silhouette Edges
When a polygon partially covers a pixel along a silhouette or geometry edge, the exact center of that pixel often lies entirely outside the polygon's boundaries. Despite the center being outside the primitive, standard pipeline behavior still evaluates the varying inputs at the pixel center via extrapolation.
+-------------------+
| (Sample 1) |
| \ | Polygon Edge
|=====\=============|==============
| \ (Center) | [Covered Area]
| \ |
| (Sample 2) |
+-------------------+
Extrapolating attribute values outside the valid range of a primitive creates several rendering issues:
- Texture Atlas Bleeding: Texture coordinates
extrapolated beyond
[0.0, 1.0]or outside dedicated sprite boundaries sample adjacent, unrelated textures in an atlas. - Lighting and Normal Discontinuities: Extrapolated surface normals can invert or normalize incorrectly, causing dark outlines, specular flickering, or inverted shading along silhouette edges.
- Mathematical Inconsistencies: Custom math functions
(such as square roots or inverse trigonometrics) may receive
out-of-range parameters, returning
NaNor invalid visual results.
How the Centroid Qualifier Resolves the Issue
The centroid qualifier changes where the GPU evaluates
fragment shader inputs when pixels are partially covered. Instead of
rigidly evaluating attributes at the pixel center, centroid
dynamically shifts the evaluation location to a position that is
simultaneously inside the pixel boundary and inside the primitive's
covered region.
In practice, the GPU selects one of the multisample locations currently covered by the polygon. Because the evaluation point is guaranteed to be within the polygon's physical geometry, values are always interpolated within the triangle's actual bounds rather than extrapolated beyond them.
Implementing Centroid Sampling in GLSL
To apply centroid sampling, apply the centroid storage
qualifier to interface variables in both the vertex (or previous
pipeline stage) and fragment shaders.
Vertex Shader Example
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
centroid out vec2 vTexCoord;
uniform mat4 uMVP;
void main()
{
gl_Position = uMVP * vec4(aPos, 1.0);
vTexCoord = aTexCoord;
}Fragment Shader Example
#version 330 core
centroid in vec2 vTexCoord;
out vec4 FragColor;
uniform sampler2D uTexture;
void main()
{
FragColor = texture(uTexture, vTexCoord);
}Both the output from the generating stage and the input to the
fragment stage must match qualifiers. If declared as
centroid out in the vertex shader, it must be declared as
centroid in in the fragment shader.
Performance and Quality Trade-offs
Using centroid introduces key behavioral differences
compared to default center-pixel sampling:
- Evaluation Position Variance: Pixels fully covered by the geometry continue to evaluate at the pixel center. Only partially covered edge pixels shift their evaluation point to an interior sample, introducing a slight derivative discontinuity between adjacent interior and edge pixels.
- Mipmap Level of Detail (LOD) Calculations: Because
texture coordinate derivatives (
dFdx,dFdy) along edges can exhibit subtle jumps when switching from center to centroid locations, anisotropic filtering or mipmap transitions may occasionally show minor variations. - Zero Overhead on Modern GPUs: Centroid calculation is handled directly by fixed-function rasterization and interpolation hardware on modern GPUs, incurring virtually no measurable runtime performance penalty over standard MSAA rendering.