Ditching Diffuse Maps - Efficient use of textures for landscape rendering
This is a followup to the previous post on terrain rendering. Hopefully this will make clear what the shader is doing in the sample file.
So here we have a terrain model, it has 3 colour layers (rock, grass, sand), an ambient occlusion layer, a specular layer, and lastly a detail layer. The usual.
One could combine 1,2,3 into one monolithic diffuse map that covers the whole mesh, and use a lower resolution texture for AO(4) and specular(5). And finally a small detail map(6) is tiled across the object to add some high frequency detail at sub-diffuse map resolution. This is the most obvious approach. At the cost of huge textures memory usage.
A better way to do it might be to have 1,2,3 as separate, tillable textures. Then an additional texture can be used to mask between them, like a stencil. Texture Splatting is apparently the term for it. AO(4), specular(5) and detail (6) stays the same. Despite using an additional texture, we can achieve much higher resolution without using gigantic textures.
Considering today’s video consoles - PS3 with 256MB of RAM, Xbox 360 with 512MB of RAM, it is obvious that memory is premium. A single 4096x4096 RGBA texture would take up 64MB, uncompressed. We need to pack more pixels into less bytes.
This is where this novel approach comes in. Basically we are storing absolutely the bare minimum image data needed to reconstruct the surface, relying on a shader material to supply some of the information that’s missing from the textures.
Here is how.
Grass is green, sand is yellow, rocks are gray. These textures typically have a rather uniform colour that don’t change much. So we should be able to set the colors of these textures in a shader, there is no point in wasting 24bit (3 channels per pixel) just to encode colour information.
So now that we are removing all the colour information from the base textures, up to four grayscale images can be combined into a single RGBA image. Yay!
Now we need a way to specify which image gets applied where. This information is stored in the R channel of the mask texture. Which, through some colour-ramp and nodal material magic, maps the grayscale image into a series of masks which can then be used to control the distribution of the textures.
Lastly, the gray textures are colorized by a the shader, combined with AO and Specular (which are stored in the G and B channel of the mask texture. And finally displayed.
First of all, recognize the fact that this approach works far better with high frequency, tileable textures such as wood/bricks/asphalt/grass than non-repeating textures such as logos/markings/etc. As such, terrain is a perfect candidate to try this texturing approach on.
Some notable features of this method: Smaller texture footprint > Less system RAM and Video RAM usage; faster loading time Higher shader complexity > More arithmetic computation; but less texture-fetch Most image compression/texture compression down-samples chroma, making this texture encoding scheme less effective.