Fractal Simplex Noise for Procedural Terrain Generation

Noise is great for procedural generation. Rather than just turning a pixel on or off in a vacuum, we apply a random gradient function over the entire output space, and so each pixel is close to its neighbors. If we interpret the output of Perlin noise as being a brightness value for each pixel, for instance, we get something like this, depending on the scale of our function:

perlinnoise2d1x2x

Like a freeze frame of the static you’d get on an old tube TV tuned to a channel that didn’t exist, kind of.

We can re-scale the noise function’s input so that the gradient bounces back and forth more or less quickly between values. Simplex noise at a very small scale looks like this:

static

Now, neither of the above are particularly believable terrain, at least not on their own. In the past, I’d tried generating terrain by taking relatively course noise, and summing it with some deterministic function, like the distance from the center of the output space, or the distance from the edges. That worked¬†okay, but resulted in very circular or very square islands, with a high peak in the center.

A better approach, at least for rapid development, is to re-scale our noise function so that we have relatively course noise responsible for the general outline of the world, and finer and finer noise functions added to it to create some excitement around the edges.

We can supply whatever value we’d like for the number of iterations – I think 5 is about right, but if you want your terrain to be more chaotic and for your daring adventurer to have less walking between mountains or bodies of water, you can reduce it.

The ‘tectonics’ function is my name for actually grabbing the noise for this iteration and adding the value to a given pixel:

That “maxElevationBeforeRescaling” variable is determined based on how many iterations we’re going to perform:

Running the code above (with the height and width supplied, and something to paint in an html5 canvas) we can get some pretty clouds:

clouds

That’s much nicer than the original static. WIth colors, we can make it clear:

And ultimately we get a pretty convincing distinction between land and water:

islands

You can hit kaiserleib.github.io/islands and refresh to get different coastlines, or view the complete source at github.com/kaiserleib/islands.

The thing that’s most impressive to me about this approach is how compact it is, given how nice the output is. With 50 or so lines of code (assuming we take the Simplex noise function as a given) we get a reasonably believable world, complete with elevation data. The generation process doesn’t mesh at all with real geology, but it’s compatible with algorithms for rainfall and erosion and biome placement and you can get a realistic-looking world out of it.

Now, it’s not terribly runtime-efficient. You have to compute Simplex noise five times for each pixel, which adds up fast. But it’s a comprehensible approach.