Terrain engine upgrade #2
I continue to work on the updated terrain engine. Today I will tell you more about detail textures.
So far, for texturing the landscape, SE has generated or loaded from disk 4 kinds of textures for each block of terrain (I will call them “maps” for clarity): elevation (height) maps, normal maps, albedo (color) maps and optionally a city / volcano glow maps. Now for the last levels of the quadtree engine generates so-called “splat” maps: they indicate which materials (detail textures) and how should be superimposed to a surface at a given point. Texture splatting is a technique commonly used for rendering of landscapes in various game engines. Each pixel of the splat map usually contains 4 weights for 4 materials, for example stones, sand, grass, snow. So up to 5 different materials can be superimposed at the same time in each terrain point (the fifth one is some “default” material that emerges when all 4 weights are around zero).
But 5 different materials for the whole planet is not enough. Therefore, in addition to the splat map, we also need a map with indexes (id) of materials. So at each point, one can still use no more than 4 + 1 materials at the same time, but their combination can vary in different places on the planet. A total count of possible different materials is 256 (four 8-bit id’s), or 64 (five 6-bit id’s, if you want to vary also the “default” material). In practice, 256 is too much, because detail textures consumes some memory; 64 seems to be enough. To increase diversity between planets, one can use an unique set of 64 materials for each of them, loading detail textures on demand into the same array. So it’s impossible to use two sets at the same time, but such situation must not occur anyway. You can’t see surface of two planets so close that detail textures appear visible, unless someone makes a mod with one planet rolls on the other one -))
The old set of 128 textures with a low resolution of 256 x 256 is replaced by a new one with resolution of 1024 x 1024 (meanwhile I collected 4 dozens of free textures from different sources). Even with compression, one texture will take 5 MB of video memory (in fact, these are two textures – colors and normals with a displacement map in the alpha channel). A set of 64 compressed textures will take 320 MB, it is quite tolerable (256 pieces would take more that a gigabyte).
I’m still experimenting with different approaches to the texture splatting. In the first version, there was only a texture with material id’s, and weights were calculated directly in the renderer shader, implementing a smooth transition (interpolation) between different materials. In this approach, the entire planet could be covered with arbitrarily alternating materials with a step of 2.5-10 meters (this is the maximum resolution of terrain textures, what you can see in all previous versions of the SE). But in this case, the transition between materials always has the same width of 2.5-10 meters. This does not allow to do a smooth transition over few kilometers, for example from sand to grass. So now I’m experimenting with the above approach with two additional maps – material id’s and weights.
Why I am saying “material”, not “detail texture”? Because the simple texture looks not so interesting as a combination of three different textures: small-scale texture, large-scale and modulation of the large-scale, to eliminate its blurriness. This method increases load on the shader three times, but I think the result is worth it. Although, in the future, it may be necessary to abandon this approach, because once implementing POM (Parallax Occlusion Mapping), the load will be too large. Such interesting materials can be implemented using splat maps, but by cost of increasing their resolution.
In the planet rendering shader, a small lookup texture is used, in which various parameters of materials are stored: id’s of four detail textures, their scales and relative weights, all this repeated four times for various surface slope, and all this for all materials defined for the planet (in its preset file). Using this texture, shader finds out all the necessary parameters for the “construction” of the given material by its id taken from the splat texture. The detail textures themselves are stored in a single OpenGL texture array.
To eliminate the highly annoying tiling (repeatability of the pattern) I tried different methods, the fastest is the method 3 by Inigo Quilez. In each pixel, the texture is sampled just twice, by coordinates shifted relative to each other, the result then is mixed. Coordinates shift occurs in areas resembling the pattern of wood (see the article).
A separate editor for the presets of materials / biomes was implemented, in order to keep the planet editor simpler. The planet editor has a drop-down list for selecting a preset, and a button for opening the preset editor. Because detail textures are superimposed in the planet rendering shader, their change in the editor becomes visible immediately, which is very convenient when configuring materials. The textures labeled “Large” in the editor are superimposed in the terrain texture generator shader, so when you change them, you need to press the “Update planet” button. For those textures I plan to implement a system similar to the one described above (combining three or more textures). But in this case textures will be made based on satellite images of the Earth, Mars and other bodies. Theoretically, if one can take also satellite elevation maps of the same regions, and superimpose them with the procedurally generated elevation maps, this way one can make a realistic mountains.
Discuss this post on the forum.