Oldest known version of this page was edited on 2006-07-20 20:45:36 by DintHer 
Articles - GLScene's TerrainRenderer
GLScene contains the object TGLTerrainRenderer
which is specifically designed for efficient rendering of terrain defined explicitly or procedurally through heightfields. (ie regular grids of height values). It does not handle irregular meshes. Huge terrains can be handled through its continuous level of detail management (LOD) and the underlying objects allow for paged terrain. TGLTerrainRenderer
uses the ROAM algorithm developed by Mark Duchaineau to reduce the vertices in the heightfield necessary to accurate depict the terrain depending on the viewers stand-point. The implementation is a variant of the split-only ROAM described by Bryan Turner and used by Seumas McNally in TreadMarks.See the ROAM homepage at http://www.cognigraph.com/ROAM_homepage/index.html∞
for detail on the algorithm and tutorial code in C. For further information on all aspects of terrain rendering see http://vterrain.org∞
GLScene provides two demonstration programs that use the TGLTerrainRenderer
– Terrain and SynthTerr which can be found under \demos\meshes\. This document is meant to help in understanding what is going on in these demos.
Firstly, it helps to understand the plumbing of key objects.
is what actually draws the terrain in the scene. It fetches the data on which the terrain is defined from a THeightDataSource
object (HDS) assigned to it. So generally the basic steps to adding terrain to a scene is to drop a THeightDataSource
descendent (eg TGLBitmapHDS
are provided in GLScene) onto the form, and then to add TGLTerrainRenderer
to the Scene. Set the HeightDataSource property in the TGLTerrainRenderer
to the HDS. When TGLTerrainRenderer
renders a scene, it divides the terrain into tiles of size
.TileSize. Eg. if the TileSize property is set to 64, then the underlying terrain is regarded as broken up into 64x64 tiles (what other terrain rendering literature would refer to as patches). If a tile is inside the view frustrum for the first time, then the renderer requests that data for that tile to be supplied to as a THeightData
object from the underlying THeightDataSource
. If the THeightData
tile is within TGLTerrainRenderer
.QualityDistance of the camera, then the tile is rendered in full detail. I.e. every point on the grid is rendered as vertex. If it is greater than this quality distance away, then the ROAM algorithm is applied to reduce the number of vertices created while still providing a good representation of the tile as viewed by the camera at that moment. Every time the view parameters change (eg moving the camera), ROAM tiles are recalculated and also tiles are checked to see whether their location with respect to QualityDistance has changed. The renderer manages a cache of rendered tiles and TGLHeightDataSource
manages a cache of Heightdata tiles.
The terrain renderer looks for all terrain right out to the limit of the view frustum – ( the “horizon limit” is given in GLScene by the current camera property DepthofView). To impose a smaller range of interest for the terrain renderer, use the event OnGetTerrainBounds. This event passes the current terrain rectangle of interest and in the event, the rectangle can be reduced to a smaller area of consideration. Note that this will mean there will be a defined edge to the viewed area unless fog or similar limiting effect is used.
A note on coordinate systems. GLScene objects use normal OpenGL coordinate space with x along screen, y up screen and z being distance behind screen. However, note that TGLTerrainRenderer
, HeightData objects reference normal map coordinates with xy being position on ground and z being height.
does not using lighting! The reason for this is that calculating a normal map on ROAMed tiles is horrendously expensive because the geometry changes virtually every frame. Because of this, the terrain should be textured with a lighting. A “lit” texture is used in Terrain but the obvious alternative is to use GLScene’s multitexturing capability and supply both a lightmap and an ordinary texture. A great deal of work is still going on behind the scenes on issues around texturing. The TilesPerTexture property is used to match texture size to terrain size.
Key properties: (play with the Terrain Demo to get an understanding of these)
HeightDataSource: Got to supply this to make it work at all. This is the object that will supply THeightData
tiles to the renderer.
QualityDistance: If any part of the tile is less than QualityDistance from the camera, then all vertices in the patch are rendered as a big triangle strip. Beyond this distance and the tiles are reduced by the ROAM algorithm. Note that when using hrsTesselated as QualityStyle, near tiles triangle count will be optimized by a high-quality ROAM pass (performed only once to produce a static high-resolution triangle mesh).
TileSize: This is the size of the square patch that is the fetched in a single HeightData object and rendered as an entity.
There is a sweet spot for performance in the combination of Tilesize and QualityDistance. If QualityDistance is too big, then none of the patches are ROAMed and vertex count gets very high. Too small and the CPU get extremely busy doing ROAM reduction on all tiles. Tilesize is similar. Too large and you have huge areas unnecessarily rendered in full resolution with little frustrum culling possible. Too small and ROAM gets very inefficient and the system slows under the load of a huge number of patches. A tile size between 32 and 128 will probably be the best choice on most hardware.
TilesPerTexture: If overlaying a 2D texture onto the terrain, this controls how the texture is matched. It details how many tiles are covered be a complete texture. Eg. Suppose the terrain is 512x512 and texture covers the entire terrain. If tilesize is 32, then texture must cover 16x16 =256 tiles (512/32 = 16).
MaxCLODTriangles : Maximum number of triangles in a scene EXCLUDING those produced from high resolution tiles. This is used as a memory allocator provide storage for ROAM triangles.
CLODPrecision : This is the control which controls the coarseness of terrain in tiles beyond QualityDistance. It is broadly interpreted as a measure of how much visual error (the variance between rendered terrain and actual terrain) is tolerable. The higher the number, the coarser will be the approximation to real terrain.
OnGetTerrainBounds : Default rendering bounds will reach depth of view in all direction (DepthofView property of a GLCamera) . Use this event to specify a smaller rendered terrain area.
By Phil Scadden