libnoise logo

A portable, open-source, coherent noise-generating library for C++


Tutorial 6: Adding realism with turbulence

In this tutorial, you'll increase the realism of a terrain height map by applying some turbulence to the noise modules that generated it.

For this tutorial, you'll start with the same group of noise modules you created in the previous tutorial.

Applying turbulence to the noise modules

A turbulence module randomly perturbs the coordinates of the input value before sending that value to its source module. Internally, a turbulence module uses low-octave Perlin noise to randomly change these coordinates.

In preparation for this tutorial, open the source file you created in the previous tutorial. The code in that file should look like this:

#include <noise/noise.h>
#include "noiseutils.h"

using namespace noise;

int main (int argc, char** argv)
{
  module::RidgedMulti mountainTerrain;

  module::Billow baseFlatTerrain;
  baseFlatTerrain.SetFrequency (2.0);

  module::ScaleBias flatTerrain;
  flatTerrain.SetSourceModule (0, baseFlatTerrain);
  flatTerrain.SetScale (0.125);
  flatTerrain.SetBias (-0.75);

  module::Perlin terrainType;
  terrainType.SetFrequency (0.5);
  terrainType.SetPersistence (0.25);

  module::Select finalTerrain;
  finalTerrain.SetSourceModule (0, flatTerrain);
  finalTerrain.SetSourceModule (1, mountainTerrain);
  finalTerrain.SetControlModule (terrainType);
  finalTerrain.SetBounds (0.0, 1000.0);
  finalTerrain.SetEdgeFalloff (0.125);

  utils::NoiseMap heightMap;
  utils::NoiseMapBuilderPlane heightMapBuilder;
  heightMapBuilder.SetSourceModule (finalTerrain);
  heightMapBuilder.SetDestNoiseMap (heightMap);
  heightMapBuilder.SetDestSize (256, 256);
  heightMapBuilder.SetBounds (6.0, 10.0, 1.0, 5.0);
  heightMapBuilder.Build ();

  utils::RendererImage renderer;
  utils::Image image;
  renderer.SetSourceNoiseMap (heightMap);
  renderer.SetDestImage (image);
  renderer.ClearGradient ();
  renderer.AddGradientPoint (-1.00, utils::Color ( 32, 160,   0, 255)); // grass
  renderer.AddGradientPoint (-0.25, utils::Color (224, 224,   0, 255)); // dirt
  renderer.AddGradientPoint ( 0.25, utils::Color (128, 128, 128, 255)); // rock
  renderer.AddGradientPoint ( 1.00, utils::Color (255, 255, 255, 255)); // snow
  renderer.EnableLight ();
  renderer.SetLightContrast (3.0);
  renderer.SetLightBrightness (2.0);
  renderer.Render ();

  utils::WriterBMP writer;
  writer.SetSourceImage (image);
  writer.SetDestFilename ("tutorial.bmp");
  writer.WriteDestFile ();
  
  return 0;
}

The above code generates a terrain height map from the following combination of noise modules:

Current noise-module diagram

As shown in the above diagram, the terrain height map receives its coherent-noise values from the output of the finalTerrain noise module.

In this tutorial, you'll create a turbulence module and connect the finalTerrain module to it, as shown in the following diagram:

Noise-module diagram with turbulence noise module

If you carefully examine the above diagram, you'll note that you'll be renaming the original finalTerrain noise module to terrainSelector since it is no longer the final noise module. You'll give the finalTerrain name to the turbulence module. Modify the following highlighted code:

  module::Select terrainSelector;
  terrainSelector.SetSourceModule (0, flatTerrain);
  terrainSelector.SetSourceModule (1, mountainTerrain);
  terrainSelector.SetControlModule (terrainType);
  terrainSelector.SetBounds (0.0, 1000.0);
  terrainSelector.SetEdgeFalloff (0.125);

Next, you'll create a turbulence noise module. To do this, instantiate the module::Turbulence class. You'll also need to connect the terrainSelector module to it as a source module. To do this, add the following highlighted code:

  terrainSelector.SetEdgeFalloff (0.125);

  module::Turbulence finalTerrain;
  finalTerrain.SetSourceModule (0, terrainSelector);

  utils::NoiseMap heightMap;
  utils::NoiseMapBuilderPlane heightMapBuilder;

Now, you'll set the the frequency and the power of the turbulence. The purpose of these methods will be explained later in this tutorial. Add the following highlighted code:

  module::Turbulence finalTerrain;
  finalTerrain.SetSourceModule (0, terrainSelector);
  finalTerrain.SetFrequency (4.0);
  finalTerrain.SetPower (0.125);

Compile and run the program, then open the tutorial.bmp file. Compare it to the original rendering from the previous tutorial:

Terrain height map with turbulence Original terrain height map

Although it is entirely subjective, the perturbed height map looks more realistic than the original height map. There's less of an ordered look to it.

Modifying the frequency and power of the turbulence

To modify the frequency and the power of the turbulence, call the SetFrequency() and the SetPower() methods, respectively.

The frequency of the turbulence determines how often the coordinates of the input value changes. The power of the turbulence determines the magnitude of these changes.

Determining the right frequency and power values to use is mostly a process of trial-and-error. A good initial value for the frequency is 2 to 4 times the frequency of the source module, while a good initial value for the power is the reciprocal of that frequency.

When applying turbulence to the source module that generates the terrain height map, the following combinations of frequency and power values make the following changes to it:

  • Low frequency and low power produce very little change to the height map.
  • Low frequency and high power produce a very 'ropey' version of the original height map.
  • High frequency and low power produce a noisy version of the original height map.
  • High frequency and high power produce a very noisy terrain height map with very little resemblence to the original height map.

The following images show the changes that the turbulence module makes to the terrain height map. The frequency (f) of the turbulence increses from left to right. The power (p) of the turbulence increases from top to bottom.

  f = 1 f = 2 f = 4 f = 8
p = 1/16 Frequency 1, power 1/16 Frequency 2, power 1/16 Frequency 4, power 1/16 Frequency 8, power 1/16
p = 1/8 Frequency 1, power 1/8 Frequency 2, power 1/8 Frequency 4, power 1/8 Frequency 8, power 1/8
p = 1/4 Frequency 1, power 1/4 Frequency 2, power 1/4 Frequency 4, power 1/4 Frequency 8, power 1/4
p = 1/2 Frequency 1, power 1/2 Frequency 2, power 1/2 Frequency 4, power 1/2 Frequency 8, power 1/2
p = 1 Frequency 1, power 1 Frequency 2, power 1 Frequency 4, power 1 Frequency 8, power 1

Now, try modifying these frequency and power values and viewing the results. Did your terrain height map change as expected?

Conclusion

In this short tutorial, you've applied some turbulence to the output values from a group of noise modules to increase the realism of the resulting terrain height map. You've also modified the properties of the turbulence by modifying its frequency and its power.