MSAA related pixel artifacts

Bright pixels randomly appear as soon as I enable MSAA. Do you have suggestions on how to fix that? Why is that even happening? As far as I understand MSAA is “coverage based”, for fragments whose sub pixels cover more than one geometry, MSAA will sample all the sub pixels for the final pixel. But why do I get such bright pixels then?

8373099--1103625--artifacts.gif
I exaggerated the effect slightly to make the pixels more visible.

1 Like

MSAA can over-interpolate values.

What I mean by that is the way MSAA works is it’ll use N coverage samples, which are at a set of subpixel positions, and if a triangle is visible it’ll render that triangle once at the center of the pixel like normal. But the triangle may not actually be visible at the center of the pixel! It’ll still render it as if it is, but using values in the fragment shader that are interpolated to a point outside of the triangle’s coverage.

This can lead to a handful of nasty artifacts, like seeing parts of a texture that shouldn’t be visible, or you can get normals that have a magnitude greater than 1.0 and may be pointing in an usually direction (like away from the camera!). That later case is what I suspect is happening here.

If you’re using the built in rendering path and the Standard shader, you can try this shader:

2 Likes

Hi bgolus,

Thank you very much. I read several of your blog posts (e.g. “The Esoteric Alpha To Coverage”) and was almost hoping you would be the one answering my question. :slight_smile: I am using the built in rendering path with custom non-standard shaders but the “centroid” interpolation qualifier was the way to go.

The shader in the image above calculates the dot product between the light direction and the normal, multiplies that with some color and the result is then transfered to the fragment shader. So by just writing:

float4 color : COLOR_centroid; // instead of just COLOR …the issue went away. :smile:

Again: Thank you very, very much!

MSAA can cause the fragment shader to run on the center of a pixel that is not covered by the polygon being rendered (imagine a far away polygon that covers only part of a pixel, not including the center).

This means the values are interpolated out of the mesh’s bounds, possibly causing issues such as UVs overflowing into neighboring pixels in the texture.

This became very noticeable for me as I was using a pixelated texture atlas with bright pink pixels outside each 16x16 block.

There is an OpenGL “centroid” qualifier to avoid this, not sure if Unity exposes this somewhere: Type Qualifier (GLSL) - OpenGL Wiki