Terrain
The Terrain plugin class provides a compute-driven, multi-level tiled terrain system optimized for real-time rendering and dynamic updates. Geometry and texture generation are performed via custom compute shaders, with support for asynchronous updates in specified regions. Internally, the terrain is represented as a single ObjectMesh containing multiple hierarchical ObjectGeometryMesh instances. Each ObjectGeometryMesh corresponds to a distinct chunk of the terrain surface, with its own set of assigned texture resources. The number of textures per ObjectGeometryMesh may vary, allowing flexible resource allocation.
Elevation and color data are regenerated only when the camera view changes. This design enables support for complex or fully procedural terrain generation algorithms in real time. The number of terrain splats does not affect rendering performance, as all splats are baked into static textures.
GeoTerrain is an Terrain plugin extension designed for planetoid objects. It can performs Mercator-to-GeoTerrain reprojection for elevation and color data using GeoTexture resources.
#include <objects/terrain/include/TellusimTerrain.h>
Example
// Create Terrain with 12 LOD levels
Terrain terrain;
terrain.setNumLevels(12);
terrain.setTileStep(0.1f);
// Create Terrain Geometry Kernel (for geometry generation)
Kernel geometry_kernel = device.createKernel().setStorages(2);
geometry_kernel.loadShaderGLSL(DATA_PATH "terrain.shader", "GEOMETRY_SHADER=1; GROUP_SIZE=%uu", 256);
if(!geometry_kernel.create()) return false;
terrain.setGeometryKernel(geometry_kernel);
// Create Terrain Texture Kernel (for texture generation)
Kernel texture_kernel = device.createKernel().setStorages(2).setSurfaces(1);
texture_kernel.loadShaderGLSL(DATA_PATH "terrain.shader", "TEXTURE_SHADER=1; GROUP_SIZE=%uu", 16);
if(!texture_kernel.create()) return false;
terrain.addTexture(FormatRGBAu8n, 256, 2, texture_kernel);
// Initialize terrain resources using the rendering device, scene graph, and shading material
if(!terrain.create(device, graph, shading_material)) return false;
// Assign the terrain texture to the shading material
Texture terrain_texture = terrain.getTexture(0);
shading_material.setShadingTexture("terrain_texture", terrain_texture);
// Configure material callbacks for pipeline creation and binding
shading_material.setCreatePipelineCallback([&](const Device device, Pipeline pipeline, Object::Type type, Material::Pass pass, uint32_t hash) {
if(pass == Material::PassDeferred) {
pipeline.setUniformMask(1, Shader::MaskVertex);
}
return true;
});
shading_material.setBindPipelineCallback([&](Command command, RenderFrame frame, Pipeline pipeline, Object::Type type, Material::Pass pass, uint32_t hash) {
if(pass == Material::PassDeferred) {
Array<float32_t> texture_layers;
terrain.getTextureLayers(texture_layers);
command.setUniformData(1, texture_layers.get(), texture_layers.bytes());
}
return true;
});
// Update terrain state
if(!terrain.update(device, sample_camera.getNode())) return false;
// Dispatch terrain compute updates
if(!terrain.dispatch(device, compute)) return false;