Generates heightmap texture images using Perlin Noise
Perlin noise is a procedural texture primitive, a type of gradient noise used by visual effects artists to increase the appearance of realism in computer graphics.
Perlin Noise is one of the techniques used to model realistic terrains. It creates more real-life like mountains and valleys. It is generated using random noise.
We compute random noise by generating a random value from 0 to 1 and assigning the texture a color based on this value
int shade = (int)(Random.NextDouble() * 255);
Sample Random Noise
For generating perlin noise we have to generate octaves of the random noise. We select pixels at intervals and linearly interpolate remaining pixels to make it smooth.
The intervals at which we select pixels is dependent on wavelength of the Perlin noise function. The best value can be differnt in differnt use cases. Using wavlength = 2.0f
is a good starting point for our project.
We can find the interpolation interval by using formula
int stride = (int)(Math.Pow(2.0f, octave_number));
We find perlin octaves for different values of octave_number and then combine the octaves to generate the final heightmap.
For the above random noise if we generate octaves for octave_number 1 to 7
we get
Octave #1
Octave #2
Octave #3
Octave #4
Octave #5
Octave #6
Octave #7
To generate perlin noise we combine the octaves generated to a final image texture. But if just average out the values in different octaves we end up with a very messy looking noise very similar to the random noise we generated earlier.
So to avoid this we use weighted average. We use amplitude to decide how much weight each octave should carry. This amplitude will define how much the octave influences the final image output. Just like wavelength, there is no best value of amplitude and should be found by experimentation of our particular use case. But amplitude = 0.5f
is a good value to start messing with perlin noise so we will use this as default value.
We the compute amplitude for each octave using formula
float amplitude = Math.Pow(0.5f, octave_number);
We then take the weighted averages and combine the result to produce the final perlin noise texture. If we have generated k
octaves we find weighted average using
float totalAmplitude = 0f;
for(int i = 0; i < k; i++)
{
float amplitude = Math.Pow(0.5f, octave_number);
totalAmplitude += amplitude;
result[x, y] += octaves[x, y] * amplitude;
}
result /= totalAmpluitude;
The reulting texture should look something like below
Sample Perlin Noise
Importing this into Unity and applying the heightmap to a terrain we get a procedural terrain with nature like mountains and valleys
Heightmap applied to terrain
Ofcouse this is not the most natural looking terrain and far from what real nature's production looks like. So I will keep exploring new techniques to make the heightmap more natural.
Some topics I plan on exploring
- Erosion simulation
- Generation using geology