A terrain isn’t textured by one pattern alone. Depending on the heightmap, there are a variety of features from sandy beaches to snowtop mountains that make up the range of possible texture combinations. With a set of textures for different landscape attributes at different heights and a heightmap, the only question that remains is: how to mix the textures? This short article will explain how the final texture for the terrain is generated.
Terrain Texture Generation Redux is a new version of my old article on flipCode, but without the horrible english!
Let’s assume that the landscape has n different attributes. For every attribute, there is a corresponding texture, for instance snow or grass. The mechanism works like this: Iterate through all pixels (x/y) in the heightmap and read the height-value at that location. Then, depending on the height, fetch the texture representing the attribute for a height-region and add that color to an output-texture at the same location (x/y). For example, a landscape that has height-values ranging from 0 to 255 could be divided like this:
- 196-255: Snow
- 128-195: Rock
- 64-127: Grass
- 0-63: Sand
The problem with this approach would be the very sharp edges on the output texture when two pixels border two regions. What would be way better is to fade the pixels from one region to another. To do that, there’s need for a fading-function.
The function shown in the sourcecode is a weighting-function and has two parameteres h1 and h2, which represent two height-values, and a third parameter w that represents the absolute height of one region. What this function does is to return a percentage value that indicates wheter h2 is in a region defined by a representative value in that region h1, for instance the upper border. The last parameter is to adjust the height of one region, so in the case of four height-regions that equally divide a range of 256 values, w would be set to 64.
Moving further with the above example: The percentage of visibility for grass for a height value of 200 would yield 0%, since at that height there’s only rocks and snow left.
In order to make it all work, some code to read and write image files is also neccessary! Assuming that it’s already been taken care off, the following code effectively does the magic:
Conclusion And Acknowledgements
Besides mixing various texturesets together into one large image, there are also other methods like texture-splatting. The method described here has the disadvantage that in order to make it look good, the texture itself has to be incredibly large, or else it will just blur out. One can counter that with a detail texture.
This article has been used by Keith Ditchburn, one of the programmers of Emperor: Battle for Dune, for his T2 Texture Generator (which by now is way more advanced than just generating textures the way it is described in this article).