Basic VTF terrain architecture
Home




Introduction

VTF terrain, for those that aren't sure, is where you use Vertex Texture Fetch to define vetice position. In this case regular grids are used, all with their height set to zero. The vertex shader then sets their height according to a height map. There are disadvantages to this system and advantages:

Advantages

. Do not need to pregenerate terrain meshes, can go straight from a height map.
. Allows for diggable terrain, just add (or subtract) to the height map.
. Allows for massive terrains as gibabytes of meshes aren't needed.


Disadvantages

. Not all cards support it. It was originally adopted by NVidia, so other cards were later to adopt it.
. Vertex texture fetches are apparently slower than pixel shader ones. I don't know the whys and wherefore's.
. Achieving an efficient terrain with minimal vertices (ie. a level of detail appropriate for that section) is awkward in some respects.
. A flat grid is not very conducive to overhangs or sheer cliffs in terrain. Not technically impossible, but not an out of the box option.
. Because texture coordinates are not defined in the vertex, some types of texturing are difficult.


There are other things, but I think they are the main points. So why am I using it? My goal is a server based game that randomly generates terrains and tunnels. When a group of clients accept that mission, they download the terrain and do the quest. The quests involve digging too. I should also say, the camera is not up close and personal, I am not going to try and compete with commercial games in that department. This system would be difficult with standard mesh terrains as they would have to download the mesh data and not just a few height maps. I am telling you this so you appreciate this is not a solution for everyone, it's just a situational technique that can be very useful in a few scenarios.



Mesh topology

I have worked on a few different systems and have settled on a grid of meshes. This allows me to frustum cull individual grids and give each grid a different level of detail, depending on it's distance from camera, regions of interest score etc. Although a height map may only be say 512 x 512 texels, a grid may have up to 16 vertices per texel (or 256 as a square). This isn't a technical limitation, rather a fideltiy that suits my requirements. Detail beyond the interpolation of the height map is achieved using a variety of techniques, as you'll see in other pages. My height map seperates dirt from rock, which is explained in the erosion page. The vertex shader only knows the difference by texture weighting, which is all it needs to know.

I use multiple heightmaps, one on top of the other, which allows for tunnels underground. You could go straight from the perlin function (I'll explain in a later page) but that would make the digging difficult.



Level Of Detail

To get level of detail, I generate 6 grids all the same size but with different sized triangles. This is not bound by 2 to the n, you can scale it however you like.


A wireframe terrain showing different grids with different fidelities.



The downside to this is you commit an entire grid to a high level of detail for perhaps just one small area. I guess it's equivalent to having to split a bi or quad terrain, but even worse. Just don't make the grids too big, and you should get some returns.


Stitching

One of the beauties of this system is how easy it is to stitch edges of terrain to neighbouring grids. If a neighbour has bigger triangles, then the verticies along that side just need to snap to the lower detail grid. Thats it, no 2 to the n limits, or worrying about split merge checks.


To stitch edges, just snap the vertices to the level of detail of your neighbour.


Note this can reduce triangles to a line but it doesn't effect the mesh as it would with a normal mesh as no texture coordinates are affected.


Popping

When you move closer to a grid, it's level of detail may increase, causing popping. To reduce this, you can morph the vertices towards the lower detail grid depending on your distance from it. Again, this is much simpler than the traditional geomorphing.




Texturizing


Perlin generated volume texture.



Calculating coordinates

You can't precalculate coordinates for the vertices themselves, and using the horizontal plane means you can't texturize cliffs or other steep triangles. For the standard 2D texture mapping, I use a uv map for each terrain section. To precalculate, I simply run along the horizontals, tallying up the distance travelled, including climbs. The UV is a fraction of the tally by the total distance travelled. This can result in some stretching but with the perlin blending, it is of little concern to me.


A worst case scenario; low LOD and lots of plane changes. The left is simple distance tallying, the right does a height box smooth first.


This system will do for now. I'm not sure how much fancy algorithms like trying to map to a hyperbola will help. See my page on volume texturizing to see how I do the perlin component.

Distance fade out

Without fading out standard 2D textures, you can end up with a noisy looking terrain. Textures with high contrast also give a tiled look, as the repeating contrasted bit becomes obvious. To avoid these problems, you need to fade your textures as the camera gets further away.


Distant terrain blends into subtle perlin noise.



Each texture is basically reduced to two colours and interpolated by the perlin noise. The two colours are close enough to be noticeable without appearing grainy. You don't need to do pixel shader texture fetches beyond the fade out threshold.



Interpolation

I use a low level of blending between the ground and rock. The interpolation is deliberately set this way so I don't have turf running half way up a cliff. To hide this, I will be using other things like rocks. This isn't a problem for high level of detail rock, but for distant terrain can be.



Multilevel terrain

I am having caves/ tunnels. My tunnels are cut away like canyons, as in a top down or 2.5D game. To do this, all I need to know is the minimum height of each level as well as the maximum height. Render in seperate passes, using a portal system (visible tunnel grid list) for the tunnels. This is necessary as most likely all tunnel grids will be high level of detail. If the player is below the minimum height for a texel on a height map, simply don't render that vertice. You could sample neighbouring texels, but I like to keep fetches to a minimum, so I use one of the texture weight values to flag don't render (set w = 0). This system allows for a smooth transition when travelling down. I use two colour channels (2 bytes) for a height value, so can fit minimum and maximum on the same map.

The VTF renderer needs to know where tunnel mouths are so it can not render terrain for those triangles. Quite simply, if the tunnel height is above the ground height, dont render that ground vertice. The minimum height defines the roof of the mouth of the tunnel. See my perlin pages on how I generate these tunnels.

You can dig the walls of tunnels too. All you need do is update the heightmap. Not exactly voxel terrain, but you can tunnel up and down, just not overlap on the same height map.


Stand by for a picture when I get the level interface (cave entrance) to a decent standard.




Conclusion

It seems a few things are easier in a way, but limited in others. You decide.



Next: Generating random terrains using rainfall and erosion


Email teatreetim@yahoo.com.au for questions. Please don't ask me for source code, but I may do pseudo code for sections if there's interest.