Rendering Terrain

Procedurally Generating Pretty Pictures

Loading, please wait

Tell me more about the...

Colors and Lighting

For something rough like stone or trees, assume the light is scattered equally in all directions. In that case, the brightness is proportional to how densely the incoming rays hit the surface.

For each RGB channel, multiply the surface color and light color together.

The surface is stone when it is higher in elevation and sloped, and vegetation when it is lower and flatter.

Stone (0) Vegetation (1)

The light and sky colors depend on the height of the sun in the sky.

Light Sky


This uses Improved Perlin Noise to compute the height, as well as basically everything else. The basic idea is that Perlin Noise is coherent, meaning that it continuous like a hill rather than discontinuous like static, and procedural, meaning that the value at each point can be calculated independently.

Traditionally, Perlin Noise is explained as an interpolation of several dot products, which is useful as an implementation guide but not so much for seeing how it works. If you want to learn more about it in that context, you should check out this, this, and this. Instead, this article will provide a more visual description.

To start with, the space is divided into cells. At each lattice point, a random direction is chosen, which affects the four cells it is a part of. In the Improved Perlin Noise, there are only four directions to choose from, but in the original there are infinitely many. Each direction creates a rotation of the same shape, shown in the animation below. When the shapes from each lattice point are added together, a smooth random-looking pattern is obtained. To see what it looks like, set the Ground Noise Gain to \(0\).

HTML5 not supported!

If you tried that, you can tell it does not look remotely realistic. It's missing all the detail found in real life. To be realistic, the noise needs to be fractal noise. So what is that?

Try listening to a note played on a piano, then the same note as a sine wave. The difference is that the piano has harmonics, additional waves with higher frequency and lower amplitude.

As the frequency of the noise increases, the height decreases -- after all, pebbles aren't a tall as mountains. Every time the frequency is doubled, the height is scaled down by a constant, called the gain.

HTML5 not supported!"


Clouds are generally bunched together, but have soft edges. This means that the cloud density should be relatively smooth. Since that restriction eliminates a simple cutoff function, we use a power function, where high and low values stay the same, but medium values are pushed down.

HTML5 not supported!"

Putting this together with the noise octaves gives the equation for cloud density.

HTML5 not supported!"

The cloud density causes the color to fade from the sky color at density \(0.0\), to \(90\%\) of the light color at density \(0.5\), to \(40\%\) of the light color at density \(1.0\).

0.0 Cloud Density 1.0

In real life, the stars are always shining, but the sun is so much brighter that our eyes adjust and we can't see them. Computer screens don't adjust to things that are very bright; they cap the color and display white. Because of this, the model compensates internally by reducing the brightness of stars when it's lighter out.

Sky Stars

The star color uses gain \(0\), and to get the correct brightness, the value is shifted down instead of scaled so the stars make distinct points. This value is added to the sky color, so the stars are hidden by clouds.

Things further away from the viewer are blended in to the sky color.

Stuff I don't see

  • Vertices are more densely packed closer to the viewer.
  • The sky is not flat - further away from the viewer it's actually closer to the ground.
  • The clouds fade away slower than the ground does to make the scene look deeper than it is.
  • Stars are not round, especially if the Star Exponent is low.
  • Because GLSL doesn't support arbitrary array lookup, instead of using a shuffled array as a source of pseudorandomness, this uses the slightly worse sine-chopping method.

Potential Improvements

  • The cloud density function can be improved.
  • More than one color of vegetation might look good.
  • Valleys are just as rough as mountains. Could be fixed by applying an exponent to the elevation, but mountain ranges have multiple peaks and the area shown might not be wide enough for valleys to be expected.
  • Ridged noise can give the mountains a nice jagged look, but doesn't look so nice for hills or forests.