Complex Procedural Terrains
Jan Aare van Gent, Kerstin Äkke
Repository
Introduction
The purpose of this project is to procedurally generate a terrain that has overhangs and caves not just changes in height.
Initial planning
We hope to make the project in UE4, but if we find it too difficult or the performance lacking, there is a chance we will switch to regular OpenGL/GLSL. It's too bad UE4 doesn't seem to support custom vertex and geometry shaders. We might be able to get similar functionality by using UE4's flagship material nodes (pixel shaders) for all shading purposes or we could use 3rd party plugins.
The project will be a demo project demonstrating how to generate complex procedural terrain on the fly. The terrain will be generated around the player/camera. If possible, we will add the ability for the camera to move freely around, while at the same time, generating new terrain.
The project will be divided into two parts:
- Block/polygon generation around the camera/player
- Density function implementation
Result
We use Unreal Engine 4, but switched from blueprints to c++ scripting. Block generation is independent from camera location. Decided to use RuntimeMeshComponent plugin instead of ProceduralMeshComponent.
Algorithm summary
Most of the algorithm used is also described in the first chapter of GPUGems3. It had to be modified due to lack of access to shaders in Unreal Engine.
- Load lookup tables
- Create noise volumes
- Calculate bottom left front corners of all blocks.
- Run marching cubes algorithm for an unbuilt block
Marching cubes
We use the Marching Cubes algorithm for mesh generation on each block. The density field (or the scalar field) will be generated via a density function.
- Based on voxel location calculate density values for unchecked corners
- Store these values in density volume
- Calculate case number
- Based on voxel location and case number calculate triangle vertices that haven't already been added to the vertices list
- Store these new vertices to an array and map their index
- Calculate and store normal of each new vertex
- Calculate and store color of each new vertex
- Add indices of triangle vertices to triangles array in correct order
- Create new mesh section using previously created arrays
Note: may result in some floating rocks.
Intermediate results 1
Program generates terrain for small area. Process is rather slow, no normals are set.

density = -pos[2] + 100 + sin(pos.X*100) * 20 + sin(pos.Y * 100)*20 + 40*(sin(pos.X*pos.X+pos.Y*pos.Y))
Intermediate results 2
Area is quite large, but not endless. Blocks further away from center have less voxels, that causes some problems around edges. Water on the floor of the scene.

example of generated terrain

example of generated terrain with water
Final result
Terrain is made up from 24x24x2 blocks. Each block contains 30x30x30 voxels with edge length of 20. The density function uses 4 noise volumes. Normals are calculated for each vertex via a gradient. Framerate has improved compared to intermediate results.

example of generated terrain