How can I generate a terrain heightmap from the perlin algorithm? I am trying to make a terrain generator (like World Machine). This is the source code I have for the perlin. The only thing that I can't figure out is how to use the perlin algorithm to generate a heightmap image.
3 Answers
A terrain heightmap texture is a regular grid of point samples, which indicate the height at that particular location on the terrain. When you want to create such a heightmap from a function f(vec2)
, you evaluate the function with the position of each of the grid points of the terrain to get the value at those points, and let that be the color value in the texture.
If the function expects the coordinate in a different space (other scale, offset, range) than the pixel coordinates of your texture, you need to map the pixel coordinates into the coordinate range you wish to invoke the function with.
The output values might have the wrong scale or offset, so you might need to compensate for those by offsetting and scaling the returned value to fit inside the range of values your texture component expects (0 through 255 for a typical 8-bit component):
foreach (y in [0..height))
foreach (x in [0..width))
vec2 p = transform_pixel_position_to_parameter(x, y);
tex(x,y) = height_offset + height_scale * f(p);
-
\$\begingroup\$ Ok! thanks. I have just a few questions: 1. What is
[0..height]
? 2. What doestranslate_pixel_position_to_parameter_space()
return? 3. What doesf()
return? 4. How can I use this code and make a grayscale texture out of it? \$\endgroup\$ Aug 27, 2011 at 19:20 -
\$\begingroup\$
[0..height]
would be the range of values from0
throughheight-1
. The two loops loop over all the pixels of a particular output texture. \$\endgroup\$ Aug 30, 2011 at 15:39
Your answer might lie in making additive multiple passes:
Pass 1: Make a 2D array storing values from the perlin generator. The bigger the array the more detail.
Then scale this array to your maximum/minimum height values for terrain.
Pass 2 through N: Offset values of array by further perlin generations, with each pass carrying a smaller weight. This should allow for further detail, taking away from the 'smoothness' of a single pass.
Now the world making suite you mentioned seems (at a glance) to support things like natural water formations/erosion over time. These can be a bit more complicated to replicate simply, but the general idea is:
Water can only lower/smooth out land, so in any place water must rest, find the deepest point, then create a quadratic gradient outwards (where higher polynomials represent further complexity, drop offs, that sort of thing).
Flora and other plant life can easily be added using rules like: Plant A can only exist a certain distance from water, and only on a circular area with an average height differential between each point less than a certain amount.
That should make for some nifty looking terrain on the cheap (processor wise).
The function has a pseudo-random appearance, yet all of its visual details are the same size (see image).
Landscapes have much more varying detail size than Perlin noise, wich is why a single 2D noise used as a heightmap looks unrealistically smooth. You can add additional layers of noise to improve this; a layer with low noise scale also should have a low weight on the overall result height. You can use irregular fractions for the scale to avoid repetitions.
World Machine seems to have a lot of additional features that don't seem to directly rely on only noise, like the valleys perpendicular to the mountains, that may be difficult or impossible to replicate this way.
Perlin noise is also relatively smooth, no matter how many layers you add onto each other, so it can't produce a mountain ridge without running an additional function on the output.
colorForPoint = normalizedValueForPoint * 255 (I presume color is a byte) * brightness
. \$\endgroup\$