bw logo

Chapter 4. Terrain

The terrain system employed by the BigWorld client integrates neatly with the chunking system. It allows a wide variety of terrains to be created in an artistic manner and managed efficiently. There are two different terrain renderers available that target different machine specifications. They are called Advanced Terrain and Simple Terrain.

4.1. Advanced Terrain

4.1.1. Overview

The advanced terrain engine uses a height map split up into blocks of 100 by 100 metres. Each block consists of height and texture information, normals, a hole map and LOD information.

4.1.2. Key Features

  • Configurable height map resolution

  • Unlimited number of texture levels with configurable blend resolution and projection angles

  • Configurable normal map resolution

  • Configurable hole map resolution

  • Per pixel lighting

  • LOD System

    • Geo mip-mapping with geo-morphing

    • Normal map LOD

    • Texture LOD

    • Height map LOD

4.1.3. Texturing

Texturing is done by blending multiple textures layers together, each texture layer has its own projection angle and blend values for blending with other texture layers. The resolution of the blend values is configurable per space and the layers themselves are stored per chunk. The textures are assumed to be rgba with the alpha channel used for the specular value.

4.1.4. Lighting

The lighting of the advanced terrain is performed per pixel. A normal map is stored per block, which is used in the lighting calculations, this is combined with the blended texture to output the final colour. The terrain allows up to 8 diffuse and 6 specular lights per block. For details of how the specular lighting is calculated see Terrain specular lighting

4.1.5. Shadows

The terrain uses a horizon shadow map for shadowing, this map stores two angles (east-west) between which there is an unobstructed view of the sky from the terrain. In the terrain shader, these angles are checked against the sun angle and the sun light is only applied if the sun angle falls between the horizon angles.

4.1.6. LOD

The purpose of the LOD system is to reduce the amount of cpu and gpu time spent rendering terrain and to reduce the memory footprint of the terrain. The terrain LOD system achieves this by reducing geometric and texture detail in the distance and loading/unloading high resolution resources as they are needed. The LODing is broken up by resource so that texture and geometric detail can be streamed separately. The LOD distances are configurable in the space.settings file, please see terrain section in space.settings for more information.

4.1.6.1. Geometry

Geometry LOD is achieved by using geo-mipmaps and geo-morphing. Geo-mipmaps are generated from the high resolution normal map for the terrain block. Depending on the x/z distance from the camera a lower resolution version of the terrain block is displayed. To avoid popping when changing between the different resolutions of the height map, geo-morphing is used, this allows the engine to smoothly interpolate between two height map levels. Degenerate triangles are inserted between blocks of differing sizes to avoid sparkles.

4.1.6.2. Collision Geometry

Collision geometry is streamed in using two distinct resolutions. The low resolution collisions are always available, whereas the higher resolution collisions are streamed in depending on their x-z distance from the camera.

4.1.6.3. Texture

Texture LOD is performed by substituting the multi-layer blending with a single top-down image of the terrain block. The LOD image is smoothly blended in based on the x-z distance from the camera. The top-down image is generated in the World Editor.

4.1.6.4. Normal maps

Normal map LOD is performed by using low-resolution and high resolution maps. The low resolution normal map is always available and the high resolution map is streamed in and blended based on the x-z distance from the camera. The normal maps are generated in the World Editor. The size of the LOD normal map is a 16th of the resolution of the normal map or 32x32 whichever value is larger.

4.1.7. Memory footprint

Since the advanced terrain allows for a number of configuration options the memory footprint of the terrain depends on the options selected.

In the Fantasydemo example provided, the terrain overhead is as follows (this information was captured using the resource counters in the Fantasydemo client, the graphics settings were set to high and the far plane was set to 1500 metres):

(this includes the textures used by the texture layers, which may also be used by other assets)

Component Size
Collision data 42,453,517
Vertex buffers 6,169,008
Index buffers 536,352
Texture layers 57,541,905
Shadow maps 26,361,856
LOD textures 35,148,605
Hole maps 4,096
Normal maps 6,572,032
Total 174,787,371

Terrain memory usage

4.1.8. terrain2 resources

A terrain2 section is contained in a chunk's .cdata file. It contains all the resources for the terrain in a chunk. The different types of terrain data are described in BNF format in the following chapter.

4.1.8.1. heights sections

The heights sections stores the height map for the terrain block. Multiple heights sections are stored in the block, one for each LOD level, each heights section stores data at half the resolution of the previous one. The heights sections are named as " heights? " where ? is replaced by a number. The highest res height map is stored in a section named heights the second highest in a section called heights1 all the way down to a map that stores 2x2 heights. This way if the height map resolution is 128x128, 7 height maps are stored in the file (heights, heights1, ... heights6)

<heightMap> ::= <header><heightData>
<header> ::= <magic><width><height><compression><version><minHeight><maxHeight><padding>
  • <magic>

    uint32 0x00706d68 (string "hmp\0")

  • <width>

    uint32 containing the width of the data

  • <height>

    uint32 containing the height of the data

  • <compression>

    (unused) uint32 containing the compression type

  • <version>

    uint32 containing the version of the data, currently 4

  • <minHeight>

    float containing the minimum height of this block

  • <maxHeight>

    float containing the maximum height of this block

  • <padding>

    4 bytes of padding to make the header 16-byte aligned

  • <heightData>

    PNG compressed block of int32 storing the height in millimetres, dimensions = width * height from the header

4.1.8.2. layer sections

The layer sections store the texture layers for the terrain block. Multiple layer sections are stored in the terrain block. Each section describes one texture layer. The layer sections are named " layer ? " where ? is replaced by a number greater than 1. I.e if the block has 3 layers, three layer sections will be stored ("layer 1", "layer 2", "layer 3")

<textureLayer> ::= <header><textureName><blendData>
<header> ::= <magic><width><height><bpp><uProjection><vProjection><version><padding>
<textureName> ::= <length><string>
  • <magic>

    uint32 0x00646c62 (string bld/0")

  • <width>

    uint32 containing the width of the data

  • <height>

    uint32 containing the height of the data

  • <bpp>

    (unused) uint32 containing the size of the entries in the layer data

  • <uProjection>

    Vector4 containing the projection of the u coordinate of the texture layer

  • <vProjection>

    Vector4 containing the projection of the v coordinate of the texture layer

  • <version>

    uint32 containing the version of the data, currently 2

  • <padding>

    12 bytes of padding to make the header 16-byte aligned

  • <length>

    the length of the texturename string

  • <string>

    the name of the texture used by this layer

  • <blendData>

    png compressed block of uint8 defining the strength of this texture layer at each x/z position

4.1.8.3. normals & lodNormals sections

The normals section stores the high resolution normal map for the terrain block. The lodNormals section stores the LOD normals for the height block, the LOD normals are generally 1/16th of the size of the normals.

<normals> ::= <header><data>
<header> ::= <magic><version><padding>
  • <magic>

    uint32 0x006d726e (string "nrm/0")

  • <version>

    uint32 containing the version of the data, currently 1

  • <padding>

    8 bytes of padding to make the header 16-byte aligned

  • <data>

    png compressed block storing 2 signed bytes per entry for the x and z components of the normal the y component is calculate in the shader

4.1.8.4. holes section

The holes section stores the holemap for the terrain block, this section is only stored when a terrain block has holes in it.

<holes> ::= <header><data>
<header> ::= <magic><width><height><version>
  • <magic>

    uint32 0x006c6f68 (string "hol/0")

  • <width>

    uint32 containing the width of the data

  • <height>

    uint32 containing the height of the data

  • <version>

    uint32 containing the version of the data, currently 1

  • <data>

    The hole data stored in a bit field of width * height, each row in the data is rounded up to 1 byte. If a bit is set to 1 it denotes a hole in the map.

4.1.8.5. horizonShadows section

The horizonShadows section stores the horizon shadows for the terrain block.

<shadows> ::= <header><data>
<header> ::= <magic><width><height><bpp><version><padding>
  • <magic>

    uint32 0x00646873 (string "shd/0")

  • <width>

    uint32 containing the width of the data

  • <height>

    uint32 containing the height of the data

  • <bpp>

    (unused)uint32 containing the bits per entry in the data

  • <version>

    uint32 containing the version of the data, currently 1

  • <padding>

    12 bytes of padding to make the header 16-byte aligned

  • <data>

    The shadow data, (uint16,uint16) * width * height, the horizon shadow data stores two angles between which there is no occlusion from any terrain or objects.

4.1.8.6. lodTexture.dds section

The lodTexture.dds section stores the LOD texture for the terrain block. The LOD texture is a low resolution snapshot of all the texture layers blended together. The texture is stored in the DXT5 format. For more information about the dds texture format please refer to the DirectX documentation.

4.1.8.7. dominantTextures section

The dominantTextures section stores the dominant texture map. The dominant texture map stores the texture with the highest blend for each x/z location in the terrain block.

<dominant> ::=<header><texNames><data>
<header> ::= <magic><version><numTextures><texNameSize><width><height><padding>
  • <magic>

    uint32 0x0074616d (string "mat/0")

  • <version>

    uint32 containing the version of the data, currently 1

  • <numTextures>

    uint32 containing the number of textures referenced by the dominant texture map

  • <texNameSize>

    uint32 containing the size of the texture entries

  • <width>

    uint32 containing the width of the data

  • <height>

    uint32 containing the height of the data

  • <padding>

    8 bytes of padding to make the header 16-byte aligned

  • <texNames>

    numTextures entries of texNameSize size containing the names of the dominant textures referred to in this map. Texture names shorter than texNameSize are padded with 0

  • <data>

    stored as a compressed bin section. byte array of width * height, each entry is an index into the texture names which indexes the dominant texture at the x/z location of the entry

4.1.9. terrain section in space.settings

The terrain section in the space.settings file contains the configuration options for the terrain. The values in the lodInfo and server sections can be modified, but the root level values should only be modified by the World Editor.

    <version> 200 (int) </version>
    <heightMapSize> uint </heightMapSize>
    <normalMapSize> uint </normalMapSize>
    <holeMapSize> uint </holeMapSize>
    <shadowMapSize> uint </shadowMapSize>
    <blendMapSize> uint </blendMapSize>
    <lodInfo>
      <startBias> float </startBias>
      <endBias> float </endBias>
      <lodTextureStart> float </lodTextureStart>
      <lodTextureDistance> float </lodTextureDistance>
      <blendPreloadDistance> float </blendPreloadDistance>
      <lodNormalStart> float </lodNormalStart>
      <lodNormalDistance> float </lodNormalDistance>
      <normalPreloadDistance> float </normalPreloadDistance>
      <defaultHeightMapLod> uint </defaultHeightMapLod>
      <detailHeightMapDistance> float </detailHeightMapDistance>
      <lodDistances>
        +<distance?> float </distance?>
      </lodDistances>
      <server>
        <heightMapLod> uint </heightMapLod>
      </server>
    </lodInfo>    
  • <version>

    The version of the terrain, this value is 200 for advanced terrain

  • <heightMapSize>

    The size of the height map per terrain block, this value is a power of 2 between 4 and 256

  • <normalMapSize>

    The size of the normal map per terrain block, this value is a power of 2 between 32 and 256

  • <holeMapSize>

    The size of the hole map per terrain block, this can be any value up to 256

  • <shadowMapSize>

    The size of the shadow map per terrain block, this value is a power of 2 between 32 and 256

  • <blendMapSize>

    The size of the blend maps per terrain block, this value is a power of 2 between 32 and 256

  • <lodInfo>

    This section contains the configurations for the terrain LOD system

  • <startBias>

    This value is the bias value for the start of geo-morphing, this value defines where a LOD level starts fading out to the next one. This value is a factor of the difference between two lodDistances.

  • <endBias>

    This value is the bias value for the end of geo-morphing, this value defines where a LOD level has fully faded out to the next one. This value is a factor of the difference between two lodDistances.

  • <lodTextureStart>

    This is the start distance for blending in the LOD texture, up until this distance, the blended layers are used for rendering the terrain.

  • <lodTextureDistance>

    This is the distance the lodtexture is blended in over, this value relative to lodTextureStart.

  • <blendPreloadDistance>

    This is the distance at which the blends are preloaded, this value is relative to lodTextureDistance and lodTextureStart

  • <lodNormalStart>

    This is the start distance for blending in the LOD normals

  • <lodNormalDistance>

    This is the distance the full normal map is blended in over, this value relative to lodNormalStart.

  • <normalPreloadDistance>

    This is the distance at which the full normal maps are preloaded. This value is relative to lodNormalStart and lodNormalDistance

  • <defaultHeightMapLod>

    This is the default LOD level of height map to load, 0 = the full height map, 1 = half resolution, 2 = quarter resolution etc.

  • <detailHeightMapDistance>

    This is the distance at which the full height map is loaded

  • <lodDistances>

    This section contains the geometry LOD distances.

  • <distance>

    The distance sections define the distances at which each geometry LOD level is blended out. distance0 is for the first LOD level, distance1 for the second LOD level etc. The distance between LOD levels must be at least half the diagonal distance of a terrain block (~71), this is because we only support a difference of 1 LOD level between neighbouring blocks.

  • <server>

    This section contains the information used by the server

  • <heightMapLod>

    This defines which LOD level to load on the server, this value is used to speed up loading on the server.

4.2. Simple Terrain

4.2.1. Key features

  • Works with the chunking system.

  • Individual grid squares addressable from disk and memory.

  • Based on a 4x4 metre grid (tiles), which matches portal dimensions.

  • Low memory footprint.

  • Low disk footprint.

  • Fast rendering.

  • Automatic blending.

  • Easy tool integration.

  • Layered terrain with tiled textures for easy strip creation.

  • Uses texture projection to apply texture coordinates to save vertex memory.

4.2.2. Overview

The terrain is a huge height map defined by a regular grid of height poles, every 4x4 metres. Terrain is organised into terrain blocks of 100x100 metres. Each of these blocks can have up to four textures, which are blended on a per-vertex (i.e., per-pole) basis. The terrain also is self-shadowing, and allows holes to be cut out of it, for things like cave openings. The terrain also contains detail information, so that the detail objects can be matched to the terrain type.

4.2.3. Chunking

The terrain integrates properly with the chunking: each terrain block is 100x100 metres, which is the size of the outside chunks. The terrain blocks are stored in separate files, so that they can be opened as needed.

4.2.4. Disk footprint

Each terrain block covers one chunk, each with dimension of 100x100 metres. It contains 28x28 height, blend, shadow, and detail values (there are two extra rows and one column to allow for boundary interpolation). Each terrain block also stores 25x25 hole values, one for each 4x4m tile.

The table below display the terrain cost per chunk.

Component Size calculation Size
Headers 256 (header) + 128 x 4 (texture names) 768
Height 28 x 28 x sizeof( float ) 3,136
Blend 28 x 28 x sizeof( dword ) 3,136
Shadow 28 x 28 x sizeof( word ) 1,568
Detail 28 x 28 x sizeof( byte ) 784
Hole 25 x 25 x sizeof( bool ) 625
Total 10,017

Terrain cost per chunk

For example, for a 15x15 km world the total disk size of the terrain would be: 10,017 x 150 x 150 ~ 215MB.

4.2.5. Memory footprint

With a field of view of 500m, and each terrain block covering 100x100 metres, a typical scene would require roughly 160 terrain blocks in memory at any one time.

The memory usage of this much terrain is about 2MB, plus data management overheads.

4.2.6. Texture spacing

The TerrainTextureSpacing tag included in the environment section of file <res>/resources.xml (for details on the precedence of entries in the various copies of file resources.xml, see File resources.xml) determines the size (in metres) to which texture map will be stretched/shrunk when applied to the terrain.

This value determines both the length and height of the texture tile.

4.3. Terrain specular lighting

The equation for the specular lighting is:

SpeClr = TerSpeAmt * ( (SpeDfsAmt * TerDfsClr) + SunClr) * SpeRfl

The list below describes each variable:

  • SpeClr (Specular colour)

    Final colour reflected.

  • TerSpeAmt (Specular amount)

    Value is given by the weighted blend of the alpha channel of the 4 terrain textures.

  • SpeDfsAmt (Specular diffuse amount)

    Initial value is stored in the variable specularDiffuseAmount in the effect file bigworld/res/shaders/terrain/terrain.fx.

    Its value can be tweaked during runtime via the watcher render/terrain/specularDiffuseAmount.

    Once the desired result is achieved, the new value can be stored in the effect file.

  • TerDfsClr (Terrain diffuse colour)

    Value is given by the weighted blend of the RGB channels of the 4 terrain textures.

  • SunClr (Sunlight colour)

    Colour impinged by sunlight.

  • SpeFlr (Specular reflection)

    Specular reflection value at the given pixel, adjusted by the Specular power coefficient

As a result of the formula, a small amount of the Terrain diffuse colour (TerDfsClr) is added to the Sunlight colour (SunClr) to give the Specular colour (SpeClr).

The initial value of the power of specular lighting is stored in the variable specularPower in the effect file bigworld/res/shaders/terrain/terrain.fx. Its value can be tweaked during runtime via the watcher render/terrain/specularPower. Once the desired result is achieved, the new value can be stored in the effect file.

Note that the Specular power can only be adjusted for shader hardware version 2.0 and later. Earlier versions of shader hardware are limited to a Specular power value of 4 (which is the default for shader hardware version 2.0 and later).

Note

The final amount of specular lighting applied to the terrain is affected by the variable specMultiplier in file bigworld/res/shaders/terrain/terrain.fx.

Set it to anything other than 1 to rescale the specular lighting, or 0 to completely disable it.

Note

Terrain specular lighting can be turned off via TERRAIN_SPECULAR graphics settings.

For details, see Graphics settings.