top of page

Procedurally Cascaded Rivers and Biomes

For the last three months, I had been working on a procedural world

generation solution, similar to what is found in Dwarf Fortress. I realised that the current isometric voxel infrastructure can be combined with a procedural world map solution to achieve one close to the unreleased version of Cube World. So I decided to adjust my development plans towards this goal and put the work for voxel destruction on hold for the time being.

The world generation solution uses Voronoi cells and Delaunay triangulation for its geometric representation. Slightly meandering rivers can be achieved by marching Voronoi cells in a directional manner.

With regards to the image above, the river network is generated from

clusters of mountain cells to lakes and coasts, thereby creating water bodies (grey) within mountainous areas. All oceans start at the border of the map and certain shoreline regions can be shallow. Lakes (light blue) are always bounded by land cells. Aquifers (cyan) are created for intermediate river junctions. River lines (blue) are drawn across a list of land cells from the source to the destination.

Clustering of Voronoi cells is used to allow only the most prominent river lines to be generated without having too much excess repetitions along common paths.

The river search paths are processed bidirectionally because there is no guarantee that the searching solution would be successful if only the forward direction is to be used. The search algorithm is designed to use a modified A* search solution that can handle a variety of special cases and pathing outcomes.

The solution mainly uses the distance to the target destination as an initial parameter to gauge the current search situation. It also needs to resolve the issue of falling into local minima, avoiding nasty infinite loop situations, and allow for backtracking in order to continue the search from a previously known location.

As there is some amount of unpredictability during the map generation, the search solution also need to handle situations where search paths are most likely not going to reach its destination. For example, they could end up reaching a nearby lake, the foot of a mountain or even a river junction. It may also be too far away from the target destination.

It also needs to avoid criss-crossing existing river paths and attempt to form river junctions using aquifers as an intermediate location if it is found to be a dead end. It also needs to avoid hugging the border of the map as the Voronoi cells there are terribly inaccurate.

Once the paths have been established, the river lines are drawn using midpoints across the shared edges of Voronoi cells. The width of rivers can be deferred to the stage of voxel generation instead.

Now for the height maps. The image above is done using the complex planet generation solution from LibNoise, with a continent frequency of 1.0 at seed zero. In order to achieve some amount of roughness at the finest cascade level, the frequency needs to be higher. At the same time, all Perlin noise attributes such as frequency, lacunarity, persistence and octave counts need to be consistent during the cascade. For larger maps instead of 256x256, the frequency needs to be increased in order to obtain multiple features, such as long mountain ranges.

However, increasing the frequency would lead to smaller continents with an increased amount of water regions. So there is also a need to add additional land with appropriate scaling and bias. This is to reduce the amount of water generated and raise the overall elevation, while preserving the shape of the continent near the edge of the world map.

With regards to the shape of the continent, currently there is a choice of either circle or ellipse shapes, which has a falloff towards the edge of the world map.

The bulk of the complex planet generation solution is retained such as mountain, valleys, badlands, oceans, etc. Their existing river solution is not adequate, so it is converted for use with drainage and inland lakes instead. There is a need to adjust the final elevation separately for each category of terrain, so lowlands remain relatively flat regions while mountains can scale up much higher to 4096 units.

The elevation is discretised then into colour bands like heat maps for easier visualisation. The red regions represent regions of the highest elevation, while orange regions represent low ridged mountains. Yellow and light orange regions represent the badlands. Green and dark green regions represent the lowlands and hills. Light blue regions represent shallow oceans while dark blue regions represent deep oceans.

The image above shows a colour band representing various discretised latitudes from the equator to the north pole. So the world generation is also dependent on terrestrial climates. Other options include equator to south pole, and between north and south poles.

Now for wind forces. Ocean regions will produce an infinite source of wind, propagating it towards the land regions using the trade wind directions. Higher land elevations will accumulate much less wind as shown in the blue regions. The trade wind direction will help determine the flow of the wind forces from the oceans.

During the process, the land elevation will adjust the trade wind direction and allow it to flow through the path of least resistance. Delta wind, wind occlusion and wind decay are required to compute the wind force that is to be accumulated by Voronoi cell receivers. The process is repeated until there is very little residue wind left for propagation.

Next is the drainage map. The complex planet solution has a section on rivers, which is converted for use in digging out sections of the world map for large lakes. At the same time, it can be used for drainage purposes. Water is mostly retained in regions represented by cyan, while dark blue regions represent regions where most water is being drained into the ground.

Drainage is used to determine wetland biomes. If the region has high drainage, less water is retained and a less wet biome would be chosen, such as bogs, as opposed to swamps or marshes. Regions with low drainage and are near rivers tend to be marshes, while swamps occupy coastal regions having low to medium drainage.

The temperature maps are next. The initial temperature is derived from the latitude and elevation. After that, the wind force is used to reduce the temperature, cooling down warm (yellow) regions of the map.

Next, the initial moisture is derived from the wind force and temperature. Mountainous regions (yellow and orange) tend to have less moisture shown in the above-left image. Lowlands receive plenty of moisture being blown from the oceans.

After that, the temperature and moisture is used to determine the rainfall. As the elevation increases, warm air rises and becomes cooler, so the moisture gets precipitated as rain. As shown in the above-right image, mountainous regions in mid-latitudes with cold temperatures gets moderate (light-blue) rainfall, while lowlands gets light (cyan) rainfall. Mountainous regions near the poles have icy and freezing temperatures, so little rainfall (yellow) is found.

The latitude, water type, temperature and salinity are used to determine the water biome. Ocean biomes (dark blue) are separated into arctic, temperate and tropical types. Shallow oceans (blue) occurs near shorelines where the elevation is not too steep.

Inland lakes (light blue) are divided into arctic, temperate and tropical types. Arctic lakes are frozen, while both temperate and tropical lakes can have differing salinity types, such as salt water, brackish water and fresh water. Mountain lakes (grey) are formed within mountain regions where rivers start to flow. Ponds (green) are formed when rivers meet at junctions.

The latitude, land type, temperature, rainfall, and drainage are used to determine the land biome. High ridged mountains near the poles will often have alpine snow and rocky terrain, while those in the temperate and tropical latitudes may have volcano craters. The image above shows an acid lake crater (cyan) in the center of some high ridged mountains.

Alpine mountain biomes can consist of snow, tundra, shrub-land, desert, rocky and glaciers. Mountain shrub-land (light brown) occurs where low drainage and light rainfall are found. If the drainage is moderate, then alpine deserts (brown) will occur instead. Badlands biomes mostly consists of desert sand and rock. It can also mix with some amount of tundra, savanna and shrub-land.

Lowlands biomes range from tundra in the poles to temperate and tropical forests, where rainfall is abundant. Tropical forests are divided into dry broadleaf (green), moist broadleaf (dark green) and evergreen (bright green), depending on the temperature and amount of drainage. If there is moderate drainage, grassland, savanna or shrub-lands maybe found instead.

If there is little rainfall, desert sand would be found instead.

The latitude, land type, rainfall, drainage and salinity are used to determine the wetland biomes. Wetland biomes always occur on rivers and near the shores of lakes and ponds. River biomes (light blue) get their salinity from outflowing lakes or mountain streams, but they only occur in the absence of dominant wetland biomes.

Swamps (dark green) occur when there is moderate rainfall and low drainage, while bogs (cyan green) occur if the drainage is higher. Marshes (yellow green) are the closest to the rivers. Mangrove swamps will occur on coastlines.

The image above is obtained after combining water, land and wetland biomes. This is for visualisation purposes only.

The next step is to cascade the river network. The image above shows the first level of the cascade. River lines (blue) represent rivers that are propagated from the parent level, while new river lines (yellow) are created. The goal is to cascade eight times until each map has very few or no rivers. New rivers will only be created for five cascade levels, after which only parent rivers will be propagated into remaining levels.

The image above is an example at level 8, where the cascade ends with just one parent river. Ponds (cyan) are formed at map borders in order to connect rivers between adjacent map tiles.

The water, land and wetland biomes are also cascaded with the river network. The Voronoi cells at the borders of each map are inaccurate so there is a need to propagate cell data between the borders of each connecting map. This is to ensure that there would be no harsh discontinuity during voxel generation.

Eventually, the cascade will end at level 8 and the image above shows an example. This region contains temperate broadleaf forest (green), with pockets of temperate shrub-land (yellow green). There is also a large temperate freshwater marsh (yellow green) residing near a river, with pockets of temperate freshwater bog (cyan green).

Upon examining the land-only biomes, it was also found that the temperate broadleaf forest also occur on the same areas as the marsh and bog wetlands. This means that the foot of the forest trees in these areas will be waterlogged with marsh and bog wetlands. This would contrast with the broadleaf forest at the lower regions of the map, which only have dry conditions at the base of their tree trunks.

For the remaining cascade images, I have put up an album on Imgur.

Lastly, I will be combining the current isometric voxel system with this procedural map generation system. Both systems are now currently stable.

This combination would allow me to achieve a near-infinite isometric world map in voxels. It would also enforce the need for a very large open world system. Thank you so much for reading!

bottom of page