With 4x MSAA, almost every GPU uses a rotated grid sampling pattern like this:
This is a single pixel. The red dot is the center of the pixel, and the green dots are the coverage sample locations. As described above, normally if a triangle covers only one of the coverage samples, the fragment shader is still calculated with interpolated values from the center of the pixel which the triangle may, or may not actually cover.
This can lead to over interpolated values, which causes things like normal directions to start pointing directions they shouldn’t. In the case above, using centroid sampling would instead use the one coverage sample’s position as the interpolation position ensuring the values exist on the triangle. If the triangle covered two or three coverage samples, the interpolated position would be the mid point between them.
This all sounds good, but when you have two triangles that share the same edge, things can get funny. The most obvious way to show this is with texture UVs. Here are the edges of two triangles that are side by side with a texture mapped across them. The blue circle is the interpolation point for the triangles.
With pixel center sampling, they match and the texture is seamless across the edge. With centroid sampling the texture is being sampled at different positions. With textures this usually isn’t really that noticeable, but it can lead to some extra aliasing that wasn’t there before. It also messes with the screen space pixel derivatives used to calculate the mip level causing potentially causing even more aliasing.
For normals on smooth geometry without extreme normal variance in the triangles’ vertices, the over interpolated pixel center normal of the triangle that doesn’t cover the pixel center will likely be fairly close to the geometry that does cover it. This means a mostly flat plane will look properly smooth. With centroid sampling the difference can be enough that slight creases can appear in the normals, especially when using specular.
For normals on geometry with extreme variance the opposite is true as the over interpolated normal produces the issues @4s4 shows, and centroid sampling would “fix” the problem by preventing over interpolated normals.
So, both pixel center and centroid sampling have problems in different scenarios. Ideally you’d want both if you could detect when one is going bad.
There’s a Valve talk related to VR where they tackle this problem. The pass both the centroid and center sampled normal to the fragment shader and try to detect when the center normal is over interpolated. If it is, they fall back to the centroid sample.
Page 44: http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
I implemented Valve’s centroid sampling technique in a shader I posted here: