An issue with standard bilinear texture
filtering is that it samples the texture using the same offsets,
regardless of how the primitive is oriented on the screen. Bilinear
filtering samples the texture four times across a 2×2 square of texels;
mipmapped filtering makes a total of eight samples (2×2 on one mipmap
level, 2×2 on another). The fact that these methods sample across a
uniform 2×2 square can be a bit of a liability.For example, consider a textured primitive
viewed at a sharp angle, such as the grassy ground plane in the Holodeck
sample from this article. The grass looks blurry, even
though the texture is quite clear. Figure 1 shows a
zoomed-in screenshot of this.
A special type of filtering scheme called
anisotropic filtering can alleviate blurriness with
near edge-on primitives. Anisotropic filtering dynamically adjusts its
sampling distribution depending on the orientation of the surface.
Anisotropic is a rather intimidating word, so it
helps to break it down. Traditional bilinear filtering is
isotropic, meaning “uniform in all dimensions”;
iso is Greek for “equal,” and
tropos means “direction” in this context.
Anisotropic can also
describe a lighting model that simulates a surface with directional
grain, such as satin or brushed metal. David Banks developed this
technique in a 1994 SIGGRAPH paper. My favorite example can be found in
the uniforms worn by the main characters in The
Incredibles. |
Anisotropic texturing is made available via the
GL_EXT_texture_filter_anisotropic extension. Strangely,
at the time of this writing, this extension is available only on older
iPhones. I strongly suggest checking for support at runtime before making
use of it.
Note:
Even if your device does not support the
anisotropic extension, it’s possible to achieve the same effect in a
fragment shader that leverages derivatives
The anisotropic texturing extension adds a new
enumerant for passing in to glTexParameter:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
The
GL_TEXTURE_MAX_ANISOTROPY_EXT constant sets the maximum
degree of anisotropy; the higher the number, the more texture lookups are
performed. Currently, Apple devices that support this extension have a
maximum value of 2.0, but you should query it at runtime, as shown in
Example 1.
Example 1. Enabling anisotropic filtering
GLfloat maxAniso; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
For highest quality, you’ll want to use this
anisotropic filtering in concert with mipmapping. Take care with this
extension; the additional texture lookups can incur a loss in
performance.