Procedurally Generating Terrain
To procedurally generate terrain while updating and rendering chunk meshes quickly, displaying only chunks within the render distacne is vital for engine performance. Otherwise, the GPU becomes overburned with draw calls as it tries to render and update a lot of chunks simultaneously. This makes the engine slower and extremely laggy.
The player's (or camera's) current position is the origin for the render distance, and the distance extends equally in all directions. So, a render distance of 1 will generate 9 chunks in a 3 x 3 grid centered around the player. My engine stores chunks within the valid range in a vector (C++ specific) named visible_chunks and iterates through it to render them. This way of managing terrain by dividing it into chunks is called space partitioning.
Note that a mesh must be drawn every frame to be properly rendered. Limiting draw calls to only visible chunks eliminates the need for additional chunk removal logic. This further helps my engine update and draw meshes fastly.
Code Implementation
/*
creates and draw chunks within a render distance.
this must be called every frame
*/
void Terrain::update() {
//gets player's x and z position in chunk space.
//note that x: width, z: length, y: height in my voxel engine.
vec2 origin = {
floor(player_pos->x / chunk_size),
floor(player_pos->z / chunk_size),
};
//checks which chunks are within the render range.
for (int x = origin.x - render_dist; x <= origin.x + render_dist; ++x) {
for (int z = origin.y - render_dist; z <= origin.y + render_dist; ++z) {
ivec2 chunk_id = { x, z }; //unique id of a chunk
Chunk* chunk = ChunkManager.get_chunk(chunk_id);
if (!chunk) {
//creates a chunk if the chunk has not been created on that position.
chunk = ChunkManager.create_chunk(chunk_id);
}
//pushes the chunk into the vector that stores only visible chunks.
visible_chunks.push_back(chunk);
}
}
//render visible chunks.
for (Chunk* c : visible_chunks) {
c->render();
}
//empties visible_chunks vector.
visible_chunks.clear();
}