I cannot leave the subject of texture compression without mentioning detail textures. These are up there with environment maps in the pantheon of awesome but underappreciated rendering techniques. Simple, efficient, and they look great.
You can think of detail textures as a kind of compression. Or maybe a simple form of procedural texture generation. They are a way of creating the illusion of an extremely high resolution texture out of several smaller images.
If you are drawing a textured object, your pixel shader probably contains a line something like this:
float4 color = tex2D(TextureSampler, input.uv);
If your texture is well drawn, this can produce a nice looking result. But if you get very close to the object, the texture will become blurry and pixelated. If you have enough memory, you could fix that by increasing the resolution of the texture, but it is not usually practical to store every texture at a ridiculously high resolution. Detail textures tackle the problem in a different way:
- Leave the original texture at a sensible, middle-of-the-road resolution
- Create a second texture, which contains an extreme close-up of fine detail (individual blades of grass, pebbles, wood grain, etc)
- Convert this second texture to monochrome
- Use a high pass filter to remove everything but the very finest detail
- Use an auto level or histogram adjustment filter to give an average brightness of 0.5
- Sample both textures in your pixel shader
- Scale up the texture coordinates before sampling the detail texture, so it will repeat more frequently than the base image
- To minimize tiling artifacts, scale up by a non integer value
- Multiply the base color by the detail, scaled x2 to preserve the original brightness
Example pixel shader code:
const float detailRepeat = 7.5; float4 color = tex2D(TextureSampler, input.uv); float4 detail = tex2D(DetailSampler, input.uv * detailRepeat); color.rgb *= detail * 2;
To show the technique in action, I used the terrain from the Lens Flare sample:
This ground texture is sized 512x512. It looks pretty good in the distance, but gets pixelated close to the camera.
Here is my second texture, which adds fine detail in monochrome:
This looks ok close up, but because it repeats so frequently, the tiling patterns are a little nasty on the distant hills.
Look what happens when I multiply the two layers together:
Nice and detailed close up. Looks good in the distance, with no visible tiling patterns. In fact, combining multiple textures like this is a great way to hide all kinds of artifacts. It can make tile repetition and DXT compression blockyness far less offensive than they would be with just a single texture.
Back when I was working on MotoGP, the artists used detail textures pretty much everywhere. There are some good examples in these screenshots from while the game was in development, and this article (on page 2) talks about the tools we used to create them.