CS559 Spring 2021 Sample Solution - Workbook 11
Written by CS559 course staff
One Way to Fix Aliasing
Note: because we changed the order of things in class, we didn’t discuss anti-aliasing basics before we are dealing with them here.
If you look at the dots on the previous page (repeated below), you’ll notice that you can see the pixel boundaries on the texture. Since something either is part of a dot or not, each pixel matters. As the dots get small, this can be ugly. This causes the jagged edges (called “jaggies” - yes, that’s a technical term).
The problem is that we are making the pixels either light or dark - nothing in between. Even if a pixel is half full of a dot, it has to be either light or dark.
A different way to look at it: for each pixel, we compute the color at the center and make the entire pixel be that color. Since that point is either inside or outside of the dot, we choose a color for a pixel.
An answer to this is to make the cutoff for inside/outside less severe. We can “blur” the dots - making the boundary fuzzy. The transition between inside and outside can be gradual. That way a pixel can be correctly on the boundary. If you select “large blur” you can see that in action. Notice that things look blurry, but the shapes are smooth (not jaggy).
To make implementing things like this easier, we use a common GLSL idiom. On the previous page, we used
step to cause the variable that measures whether we are “inside the dot” to switch from 0 to 1 as the distance to the dot center gets to be bigger than the radius. Here, we change that to use the
smoothstep function which gradually transitions from 0 to 1 over a range centered at the threshold. The width of this range is the “blurriness”. Since we are using the
mix function, if we are in the transition zone, we get a blend of the colors.
Can we have both sharp edges and no jaggies? Try “correct anti-aliasing” and see what is the best we can do easily. We’re still blurring the edge, we’re just making the blurriness be one pixel in width (rather than fixed in UV space). GLSL has support to help us do that. Basically, you take the derivative of
v with respect to screen coordinates to see how much they change. This is a slightly advanced topic - but it is really important for making nice looking texturing.
GLSL can compute the derivative of a value (like u and v) with respect to screen space x and y. It basically tells us how much the value changes between pixels. It has a convenient function
fwidth that is used in the shader to make the “correct anti-aliasing” - it basically computes the magnitude of the vector derivative (in x and y directions).
Note that this is exactly the same problem as trying to figure out what level of the mip-map to look up when we filter image-based textures.
Exercise: Anti-Aliased Checkerboard
This is a harder exercise. Make a version of your checkerboard shader that is anti-aliased!
You can figure out how to do it from the dots example on this page. The starting code can be found in 11-07-02.js (11-07-02.html) and the shaders are in shaders/11-07-02.vs and shaders/11-07-02.fs. A hint: make a non-anti-aliased checkerboard using
mix to switch between the colors. Then switching to
smoothstep will be easy.
You should not load an image and use a texture map - which is easy to anti-alias with mip-map filtering. For this exercise, write a procedural shader.
Note: it is OK if you make blurry edges (using a constant value instead of fwidth).
If you get jaggy looking textures, you need to do something about it. This is called “anti-aliasing”.
For now we’ll move on to Next: Using Textures and learn about how to use images in textures.