Question

Perlin explained in pseudo-code: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

The tutorial gives me a random number generator function writen in pseudo-code. Returns a floating number in the range of (-1, 1).

function IntNoise(32-bit integer: x)             
    x = (x<<13) ^ x;
    return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);    
end IntNoise function

So if this function returns a number in the range (-1, 1), can't I just use random.uniform(-1, 1)? But then I meet this problem:

function Noise(x)
.
.
end function

function SmoothNoise_1D(x)
    return Noise(x)/2  +  Noise(x-1)/4  +  Noise(x+1)/4
end function

I guess the Noise(x) function generates random numbers for 1D noise.

I can't seem to understand what the x parameter is. Is it a seed? And, can't I use random.uniform(-1, 1)

Was it helpful?

Solution

The noise function used in Perlin noise is a seeded random number generator. That is, it must return the same value every time it is called with the same value for parameter, X. You can think of X as some position in space in a given dimension between the bounds of the region you're computing Perlin noise over.

You can use the Python random module if you can reset the state of the RNG based upon your given parameter so it always returns the same value for a given X.

import random

rand_state = random.Random()

def Noise(x):
  rand_state.seed(x)
  return rand_state.random()

>>> Noise(1)
0.13436424411240122
>>> Noise(2)
0.9560342718892494
>>> Noise(1)
0.13436424411240122

Note that Noise returned the same value when passing 1 in the first time, and the second. It also returned a different value when value other than 1 was input. The parameter to seed can be any hashable type in Python. For your purposes, any numeric type works.

Typically when creating Perlin noise, many calls are made to this Noise function, so you'll want it to be fast. On my machine, it takes about 14 microseconds to execute the function above. That's only ~70000 calls per second. It may be that implementing the pseudocode for IntNoise may result in better performance. Infact, the following method:

MAX_INT = (1<<31)-1
def IntNoise(x):
    x = int(x)
    x = ((x << 13) & MAX_INT) ^ x
    x = ( x * (x * x * 15731 + 789221) + 1376312589 ) & MAX_INT
    return 1.0 - x / 1073741824.0

Seems to take on average about 1.6 microseconds per invocation, or about 10 times faster than the Noise above. Its range of return values is is (-1, 1), but that can be changed by modifying the last line. I can't speak to the uniformity of its distribution, however, a picture is worth a thousand words. Blue dots below are from IntNoise, and red dots are from the python random.uniform function.

Plot of IntNoise

The Noise function above can be used by the smooth noise algorithm in your question. The URL you linked in the question describes what the smoothing functions are for better than I could. After reading the paragraph, study the pictures of 1D and 2D smoothing next to it to better understand their purpose.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top