Texture filtering: anisotropy

Originally posted to Shawn Hargreaves Blog on MSDN, Thursday, September 24, 2009

Mipmapping allows textures to be scaled down by any amount while maintaining high quality filtering and cache-friendly memory access patterns. But mipmaps don't work so well when different axes are scaled by different amounts:

 Untitled

How do we choose which mip level to use for the elongated cat?

Non uniform scaling is rare in 2D (although my cat has been eating so much lately, he is well on the way to horizontally scaling up his belly exactly like the above image :-) but it happens all the time in 3D:

 Untitled8

Any time you apply a perspective transform to a textured triangle which is not exactly facing the camera, non uniform scaling will result.

Anisotropic filtering improves the quality of these situations by recognizing when textures are being scaled differently in different directions, and taking a larger number of samples to compensate.

To enable it:

    device.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
    device.SamplerStates[0].MagFilter = TextureFilter.Linear;
    device.SamplerStates[0].MipFilter = TextureFilter.Linear;
    device.SamplerStates[0].MaxAnisotropy = <n>;

MaxAnisotropy is typically set to 2 or 4. Some recent cards support as high as 16, so check the caps to see how high yours can go.

How it works:

How does it look? Here is our favorite landscape with mipmaps but no anisotropic filtering:

image11

And now with mipmaps plus anisotropic filtering:

image14

Both images are free from noisy aliasing, but the anisotropic version has better texture detail on surfaces which are angled relative to the camera, and is less blurry.

So why doesn't everyone use anisotropic filtering all the time?

Because this quality improvement comes at a price! Sometimes a high price. All these extra samples take time for the texture unit to compute, and cost extra memory bandwidth too.

Or it might be free. If your game is CPU bound, or bottlenecked by a different part of the GPU, anisotropic texture fetches might not actually slow things down at all. So try turning it on and see what happens. If it is too slow with a high MaxAnisotropy setting, try a smaller value to find the right balance between quality and performance.

Back when I was working on MotoGP, we wanted anisotropic filtering for quality reasons, but couldn't afford to use it everywhere. We ended up tweaking MaxAnisotropy differently for every texture, setting it to 4 for billboard adverts where the quality improvement was especially noticeable, to 3 for most of the road surface and grass, and 2 for less important things like trees and crowds. We sometimes even used different settings for each layer of a multitexturing shader, for instance a high anisotropy for the base texture but none at all for the detail texture.

Blog index   -   Back to my homepage