Texture mapping: The Third Way
Sunday, August 24th, 2003Surely there’s nothing I can say about texture mapping that hasn’t been said already? Well I’m going to have a go, on the sub-topic of filtering.
Normally you have this paradigm that says you can have your textures filtered or unfiltered. In the old days [more than 5 years ago] filtering was expensive, because it had to be done in software, but these days it is used by default in 3D hardware acceleration.
To illustrate, here is a detail of a texture map, close up and ever so slightly rotated, rendered without filtering and with filtering respectively:
Un-filtered |
Filtered |
We [computer programmers & designers] tend to accept that we can choose one or the other… we can have super crappy blocky pixels [in certain circumstances much faster to render] or we can have soft blurry fuzz, using bilinear [or bicubic] filtering. Now my problem with this dichotomy is that sometimes you might not want your pixels to be all fuzzed together… maybe you want them to be square [imagine tarmac with sharp edged lines and block letters on it… filtering will just make it look intolerably blurry]
So what’s wrong with un-filtered textures?
What many people don’t realize is that turning off filtering actually results in two levels of pixellation:
-
Pixels from the source image appear as whole squares.
-
Edges between the squares are also pixellated, resulting in jaggies - see detail of white pixel.
Because of 2, non-filtered textures look crappier than they need to. But these jaggies have nothing to do with the source image! If we are rendering a field of sharp edged squares the edges of those squares should look like straight lines, not staircases.
But how can we anti-alias the edges of the squares without the squares themselves becoming blurry? Easy! Un-filtered textures and anti-aliasing are NOT mutually exclusive. We just use a modified bilinear filtering algorithm, but we adjust it so that it only filters the pixel thick edges of the squares [this is a slight over-simplification].
Anyway, I have an algo which does this, allowing a sliding scale of bilinear filtering (from "non" to "full"):
Non-filtered |
Edge-filtered |
Half-filtered |
Full-Filtered |
The reason I’m writing this now is because I have been doing some work programming for 3DSMax lately, and was surprised to discover that even though its renderer anti-aliases everything else (so that polygon edges are not jaggy) it still does not do any anti-aliasing within un-filtered texture maps.
Note that the patterns on the cube pictured to the right clearly exhibit jaggies between the checkers, while the actual cube edges are lovely and smooth [just as you’d expect them to be]. This inconsistency makes the rendering look a bit crummy, and makes it hard to imagine a use for non-filtered textures in 3dsMax.