Skip to content

2D perlin noise map generator

1
2
3
4
5
6
%matplotlib inline
import matplotlib.image as mpimg
import scipy.ndimage as ndimage
import matplotlib.pyplot as plt
import numpy as np
import random

implementation of perlin noise

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
n = 6
raw_noise = np.zeros(shape=(n+1, n+1,2))

# initialize random seed
np.random.RandomState(42)

# fill raw noise with random unit vectors
for i in range(n+1):
    for j in range(n+1):
        # TODO: very inefficient loop!
        x = np.random.normal()
        y = np.random.normal()

        # normalize:
        mag = (x**2+y**2)**.5
        x /= mag
        y /= mag

        raw_noise[i,j,0] = x
        raw_noise[i,j,1] = y 
1
2
3
4
5
6
fig1, ax1 = plt.subplots()

ax1.imshow(np.linalg.norm(raw_noise, axis=2), cmap='binary')
#print(img_binary)
ax1.set_title("raw noise map (magnitudes of vectors on unit-circle)")
plt.show()

png

1
2
3
4
5
6
7
8
def lerp(a0, a1, w):
    return a0 + w*(a1 - a0)

def dotGridGradient(ix, iy, x,y):
    dx = x - ix
    dy = y - iy

    return dx * raw_noise[ix, iy,0] + dy * raw_noise[ix,iy,1]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def perlin(x,y):
    x0 = int(x)
    y0 = int(y)

    x1 = x0 + 1
    y1 = y0 + 1

    sx = x - x0
    sy = y - y0

    n0 = dotGridGradient(x0,y0,x,y)
    n1 = dotGridGradient(x1,y0,x,y)
    ix0 = lerp(n0,n1,sx)

    n0 = dotGridGradient(x0,y1,x,y)
    n1 = dotGridGradient(x1,y1,x,y)
    ix1 = lerp(n0,n1,sx)

    return lerp(ix0,ix1,sy)
1
2
3
4
5
6
7
perlin_factor = 32
n_perlin = perlin_factor*n
perlin_noise = np.zeros(shape=(n_perlin, n_perlin))

for x in range(n_perlin):
    for y in range(n_perlin):
        perlin_noise[x,y] = perlin(x/perlin_factor,y/perlin_factor)
1
2
3
4
5
6
fig2, ax2 = plt.subplots()

ax2.imshow(perlin_noise, cmap='binary')
#print(img_binary)
ax2.set_title("stupid interpolated perlin noise map")
plt.show()

png