Sarah Yoo

Building a Basic Terrain System

Chunk

A chunk is made up of blocks, and a terrain is made by stitching together many chunks.

To programatically generate natural-looking terrain, I use a heigt map, which is a grid of elevation values typically created with Perlin noise. This gives the terrain its hills, valleys, and natural variation.

Before building a chunk mesh, I loop through its blocks and assign a block type based on its height relative to the height map.

For example:

for (int x = 0; x < width; ++x) {
	for (int z = 0; z < length; ++z) {
		for (int y = 0; y < height; ++y) {
			BlockType type = Air; //default block type is air
			int h = height_map[x][z];
			if (y > h && y <= water_level) {
				type = Water;
			}
			if (y == h) {
				type = Grass;
			}
			if (y < h) {
				type = Dirt;
				if (y < h - 5) {
					type = Stone;
				}
			}
			if (y <= h && y >= h - 2 && y + 1 < height && y + 1 <= water_level) {
				type = Sand;
			}
			blocks[x][y][z].type = type;
		}
	}
}

This code snippet ensures

  • Grass blocks appear at the surface (as defined by the height map).
  • Dirt blocks are placed just below the grass layer.
  • Stone blocks are formed underground, if they are more than 5 blocks below the surface.
  • Water fills the space above the terrain but below a defined water level.
  • Sand appears near shorelines; just below the surface if there's water above.
  • The remaining blocks are left as Air.

This block type assignment should happen before mesh generation, since any change in block type means changing a block's texture.

Sarah Yoo