Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm using 2d perlin noise to generate a heightmap and then adding 3d perlin noise to the heightmap to create overhangs and ridges. But it's not turning out like I would like it to. There are too many hills that don't look good and lots of different places where it's flat. This is the perlin noise function I'm using for both the 2d and 3d (in LUA):

function noise(x, y, z) 
  local X = math.floor(x % 255)
  local Y = math.floor(y % 255)
  local Z = math.floor(z % 255)
  x = x - math.floor(x)
  y = y - math.floor(y)
  z = z - math.floor(z)
  local u = fade(x)
  local v = fade(y)
  local w = fade(z)

  A   = p[X  ]+Y
  AA  = p[A]+Z
  AB  = p[A+1]+Z
  B   = p[X+1]+Y
  BA  = p[B]+Z
  BB  = p[B+1]+Z

  return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ), 
                                 grad(p[BA  ], x-1, y  , z   )), 
                         lerp(u, grad(p[AB  ], x  , y-1, z   ), 
                                 grad(p[BB  ], x-1, y-1, z   ))),
                 lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  
                                 grad(p[BA+1], x-1, y  , z-1 )),
                         lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                 grad(p[BB+1], x-1, y-1, z-1 )))
  )
end


function fade(t)
  return t * t * t * (t * (t * 6 - 15) + 10)
end


function lerp(t,a,b)
  return a + t * (b - a)
end


function grad(hash,x,y,z)
  local h = hash % 16
  local u 
  local v 

  if (h<8) then u = x else u = y end
  if (h<4) then v = y elseif (h==12 or h==14) then v=x else v=z end
  local r

  if ((h%2) == 0) then r=u else r=-u end
  if ((h%4) == 0) then r=r+v else r=r-v end
  return r
end


p = {}
local permutation = {151,160,137,91,90,15,
  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
}

for i=0,255 do
  p[i] = permutation[i+1]
  p[256+i] = permutation[i+1]
end

You can also find the implementation, written by Perlin himself, here: http://mrl.nyu.edu/~perlin/noise/

And this is how my loop looks like:

local smoothness = math.random(20, 30)
    for x = 1, mapScale do
        wait()
        for z = 1, mapScale do
            local height = noise(x/smoothness, z/smoothness, 0) --Find out the height 
            for y = 1, (height*mapHeight)+10 do
                local density = noise(x/smoothness, y/smoothness, z/smoothness) --Find out the density
                if y > waterLvl then
                    if density*10 > 0 then
                        t:setCell(x, y, z, 1, 0, 0) --Sets cell at position x, y, z
                    end
                else
                    t:setCell(x, y, z, 1, 0, 0)
            end
        end
    end
end    

This is how it turns out to be: http://i43.tinypic.com/fk7acm.png

How would I change the frequency, number of octaves, and persistence with this function since it doesn't take any parameters for them?

share|improve this question
2  
Greetings, user, and welcome to the GameDev stack. You say your code is not producing output you like. Can you show us the output you're getting, and indicate why/where it's not matching up with your expectations? –  fnord Jul 5 '13 at 22:22
1  
Perlin noise is just a guaranteed smooth, random distribution of data from 0..1. 3D perlin just makes it smooth in a cube. What do you expect to see? –  Patrick Hughes Jul 5 '13 at 22:36
    
I added a picture so you can see how it looks like. –  Spynaz Jul 5 '13 at 23:28
1  
You could also check out libnoise, featured in a related answer. –  congusbongus Jul 6 '13 at 0:24
3  
At this point you need to read the documentation to the two noise libraries mentioned, and then if there's a term you don't understand it then head to google. For example, libnoise has a really nice glossary libnoise.sourceforge.net/glossary to get you started. –  Patrick Hughes Jul 6 '13 at 19:32
show 4 more comments

1 Answer

You are ONLY generating Perlin noise. This is actually the same as using only one octave, at any frequency. You can base yourself to implent FBM (Fractional Bownian Moment), It is actually how all engines use to make Perlin noise more fractal looking.

Bringing it down to code, you can use it like this:

//pseudo code
function fBm(float x, float y, float z, int octaves = 8, float lacunarity = 2.0, float gain = 0.5)
{
    float amplitude = 1.0;
    float frequency = 1.0;
    float sum = 0.0;
    for(int i = 0; i < octaves; ++i)
    {
        sum += amplitude * noise(x * frequency, y * frequency, z * frequency);
        amplitude *= gain;
        frequency *= lacunarity;
    }
    return sum;
}

You can change this line

sum += amplitude * noise(x * frequency, y * frequency, z * frequency);

with some other noise functions to generate some cool effects, for example:

sum += amplitude * (1-abs(noise(x * frequency, y * frequency, z * frequency)));

and you'll have a cool eroded terrain, with lots of straight mountains. Having a nice terrain is a game of playing with parameters, don't expect a already made "recipe", try to make your own!

share|improve this answer
    
Thanks a lot! That seems to make my terrain look a bit better. –  Spynaz Jul 7 '13 at 16:44
    
One tip is to try to render the generated heightmap on an texture, then saving it on disk. Should help a lot to understand how your noise is looking. –  Gustavo Maciel Jul 7 '13 at 16:48
    
@Spynaz If the answer helped to solve your problem, please mark it as accepted. –  Gustavo Maciel Jul 9 '13 at 6:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.