Dynamic landscape generated from procedural heightmap
Learing to create a procedural virtual landscape was how I originally learned 3D computer graphics. Much of my work is still informed by Reimer’s XNA tutorials, (which are now offline, but have backed up at this location). I started by modifying code from this tutorial series, and eventually I created my own landscape rendering platform in Unity. For my Dynamic Landscape projects, I have created a terrain generation program that can produce a wide variety of landscapes at various scales. There are many landscape generators that are much more realistic and convincing, but for my work, I want to have full control of this foundational process. Furthermore, I want to create a system where I can specify basic land forms, such as fjords, islands, valleys and mountain watersheds that are consistent within a specified random range.
I have spent quite a while looking at elevation data for regions within the West Coast Mountains and Rocky Mountains, where there are stunningly beautiful landscapes and water features that form in fractal-like patterns. For a particular watershed, mountains feed streams from snow melt, which flow into increasingly large river systems that eventually empty out into the ocean, spreading over fluvial planes in branching patterns. Such a landscape would appear to be alive overtime, where the seasonal pulse of weather patterns drive land formation processes between rock and water.
Complex mountain ranges, valleys, winding rivers, and sprawling deltas are dramatic formations that I hope to approximate in an interactive simulation environment. As with my other interactive simulations, I do not seek to replicate nature, but rather to convey the essentials of landscape relationships and ecological processes. The landscapes that I usually work with are highly compressed in space, where a viewer can see mountains, valleys, rivers, estuaries and oceans within a single frame. Such watersheds would not exist in reality, but in virtual space, these landscape can function both as an animated painting and a diagram of landscape interactions.
Elevation data (height map) for Olympic Peninsula, Washington
As I often create virtual landscapes from GIS data, I use height maps to generate procedural terrain. A Height map is a black and white image with elevation ranges from 0-1 that correspond to minimum and maximum elevation values, which can be multiplied by a scalar height value to define the steepness of 3D terrain. A simple height map is easy to generate procedurally, but it can be difficult to create realistic terrain from code.
In the past, I created procedural terrain from Perlin noise, which is pseudo random noise produced by a gradient mathematical function. Perlin noise can be iteratively scaled down and combined to produce a fractal like result that works fairly well for basic terrain. Previously, I implemented some rudimentary erosion and water formation steps on a Perlin noise based-height map, which I used in projects such as Evolutionary Forest and Uncertain Associations. However, the water systems of these landscapes are quite unrealistic, where crude rivers flow into disconnected bowls. These water systems create blob like-shapes that directly mirror perlin noise, with diagonal arms leading down into central basins.
Simple lakes and terrain in Evolutionary Forest. Perlin noise is evident in shapes of lakes and mountains.
Updated Terrain Generation Approach
Restarting from scratch, I have created a new terrain generation system based on Voronoi Noise. Voronoi diagrams are often used to simulate natural forms such as bubbles, dragonfly wings and are also used to create procedural landscapes. From a Vononi noise gradient, it is easy to imagine landscape features similar to mountains and river valleys. Voronoi Noise divides an image into cells, where each cell has a high point placed randomly within the cell. Between these high points, a gradient value is calculated for each pixel, which is the distance to the nearest high point of all neighboring cells. A simple voronoi landscape approach creates uniform cones that have distinct edges between them. I added a few variables to adjust the base slope and shape of these cones.
To create ridges between mountains that are close by, I accumulate a distance value between all neighboring voronoi cells. This approach is similar to implicit modeling, where each mountain is a point in a distance field. These ridge values can also be shaped by a multiplier and power function. To improve landscape complexity, I merge the original Voronoi Noise data with a second order, more detailed voronoi gradient. This effect is subtle and can easily create a very chaotic landscape.
To improve the realism of voronoi based terrain, I multiply these height values by ridge noise derived from perlin noise, and mix in a small amount of this noise into the resulting height maps. The resulting terrain looks much better than simple perlin noise, and the landscape has convincing mountains, rivers, wetlands and valley floors. This entire landscape generation process is done with the CPU, which can be broken up across many stages to run smoothly in real time.
Another simple, but powerful step to improve my terrain height map is to apply distortion to the 2D image. This image-based distortion produces sharp ridges, steep cliffs, plateaus and curving river valleys. The resulting height map is far from realistic, but this process is fast and can produce a wide range of landscapes. I use Distortion a lot, which I implement by using a normal texture of ocean waves, where the xy values of the normal data adjust sampling positions of the source image.
Resulting landscape from components of height map generation.
The primary goal of my revised terrain generation system is to create landscapes that have realistic watersheds, where elevation values flow down in a continuous gradient that leads into an ocean. I want to minimize “sinks” where water flows into but does not escape. I also want to produce generative landscapes that are semi-structured, where I can define control points so that I can create landscapes with predictable features. Many of my artworks have a fixed camera at the front of a landscape, where I usually want mountains in the background, hills in the middle ground and lowlands in the foreground. I also want to be able to create specified landforms, such as a coast line, island, peninsula or valley that is oriented to the “front” of a landscape. Using my combination of voronoi and perlin noise with distortion produces better connectivity between rivers, wetlands and lakes that my previous work. However, there are still many sinks where water flows in from all sides.
Thinking of each vononoi cell as an individual mountain, I decided to create a separate system of gradient nodes that can be used to modify vononoi cells. So far, I am using these “gradient nodes” to alter the height values of neighboring Voronoi cells. To create specific landforms, I can specify height range values for gradient nodes. In general, this simple technique can be used to create more realistic terrain that can be randomized or partially structured. I have defined control points for gradient nodes on the corners and center points of the image. With values within a specified range, I can easily create basic landforms with a convincing watershed. Finally, I use these gradient nodes to create elevation data that is added to the voronoi height map to tilt terrain forms along a gentle gradient. This approach to used gradient nodes allows me to further improve the realism of terrain watersheds.
Semi-structured landscape with two main watersheds leading into ocean.
I have used this new terrain generation system with Mycelial Forest to create a flat foreground, with slowly rising mid-ground and distant background mountains. I also used this system to generate coastal landscapes for Hydrosheds, where continuous water systems flow from small mountains into the ocean. In each of these artworks, I wanted specific terrain forms with consistent properties in the foreground scene. Each project specifies settings for terrain control points, as well as a range of terrain height.
In general this approach has worked very well so far, and I greatly improved the visual aesthetics of my base terrain forms. This terrain generation process takes about 1 second, which is perfectly fine for the context of interactive applications. Creating good terrain is crucial for working with water simulation, which is discussed in my Dynamic Water Simulation page. More work can be done to improve procedural landscapes, and there are many approaches to creating procedural terrain.