This class provides functionality to render heightfields of large sizes utilizing the GPU. Internally a quadtree is used to generate the LODs. The final terrain is then rendered using instancing on the GPU. This makes it possible to use very large heightfields (8192+) with very reasonable performance. The terrain provides options to control the LOD using a target triangle width, see
Because the Terrain is rendered entirely on the GPU, it needs a special vertex shader. There is a default vertex shader available, which you can use in your own shaders. IMPORTANT: If you don’t set an appropriate shader on the terrain, nothing will be visible.
This constructs a new terrain mesh. By default, no transform is set on the mesh, causing it to range over the unit box from (0, 0, 0) to (1, 1, 1). Usually you want to set a custom transform with
This generates the terrain mesh, initializing all chunks of the internal used quadtree. At this point, a heightfield and a chunk size should have been set, otherwise an error is thrown.
If anything goes wrong, like a missing heightfield, then an error is printed and false is returned.
std::size_t get_chunk_size(void) const
This returns the chunk size, previously set with
bool get_generate_patches(void) const
This returns whether patches are generated, previously set with
Texture *get_heightfield(void) const
This returns the terrain heightfield, previously set with
PN_stdfloat get_target_triangle_width(void) const
This returns the target triangle width, previously set with
bool get_update_enabled(void) const
This returns whether the terrain is getting updates, previously set with
void set_chunk_size(std::size_t chunk_size)
This sets the chunk size of the terrain. A chunk is basically the smallest unit in LOD. If the chunk size is too small, the terrain will perform bad, since there will be way too many chunks. If the chunk size is too big, you will not get proper LOD, and might also get bad performance.
For terrains of the size 4096x4096 or 8192x8192, a chunk size of 32 seems to produce good results. For smaller resolutions, you should try out a size of 16 or even 8 for very small terrains.
The amount of chunks generated for the last level equals to (heightfield_size / chunk_size) ** 2. The chunk size has to be a power of two.
void set_generate_patches(bool generate_patches)
If this option is set to true,
GeomPatcheswill be used instead of
GeomTriangles. This is required when the terrain is used with tesselation shaders, since patches are required for tesselation, whereas triangles are required for regular rendering.
If this option is set to true while not using a tesselation shader, the terrain will not get rendered, or even produce errors. The same applies when this is option is not set, but the terrain is used with tesselation shaders.
void set_heightfield(Texture *heightfield)
This sets the heightfield texture. It should be 16bit single channel, and have a power-of-two resolution greater than 32. Common sizes are 2048x2048 or 4096x4096.
You should call
generate()after setting the heightfield.
void set_target_triangle_width(PN_stdfloat target_triangle_width)
This sets the desired width a triangle should have in pixels. A value of 10.0 for example will make the terrain tesselate everything in a way that each triangle edge roughly is 10 pixels wide. Of course this will not always accurately match, however you can use this setting to control the LOD algorithm of the terrain.
void set_update_enabled(bool update_enabled)
This flag controls whether the terrain should be updated. If this value is set to false, no updating of the terrain will happen. This can be useful to debug the culling algorithm used by the terrain.