Skip to content

Instantly share code, notes, and snippets.

@dragon0
Created December 1, 2017 22:01
Show Gist options
  • Save dragon0/f70e2637e6d4e64a6ab210faf8a85a50 to your computer and use it in GitHub Desktop.
Save dragon0/f70e2637e6d4e64a6ab210faf8a85a50 to your computer and use it in GitHub Desktop.
Perlin noise generator based on pseudocode from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
#!/usr/bin/env python3
'''
Perlin noise generator based on pseudocode from
http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
'''
import math
def linear_interp(a, b, x):
return a * (1 - x) + b * x
def cosine_interp(a, b, x):
ft = x * math.pi
f = (1 - math.cos(ft)) / 2
return a * (1 - f) + b * f
def noise1d(a, b, c):
'''
Returns a noise function. a, b, and c are large prime numbers.
eg:
a = 15731
b = 789221
c = 1376312589
'''
def noise(x):
x = (x<<13) ^ x
return (1.0 - ((x * (x*x * a + b) + c) & 0x7fffffff)/float(0x40000000))
return noise
def smooth1d(noise):
'''
Returns a smoothing function for the supplied noise function.
When called, the smoothing function returns the average of the input and its neighbors.
'''
def smooth(x):
return noise(x)/2 + noise(x-1)/4 + noise(x+1)/4
return smooth
def interp1d(noise, interp):
'''
Returns an interpolator function.
Parameters are the (possibly smoothed) noise function and an interpolation
function to apply to the noise.
'''
def interpolated(x):
fx, ix = math.modf(x)
ix = int(ix)
v1 = noise(ix)
v2 = noise(ix+1)
return interp(v1, v2, fx)
return interpolated
def perlin1d(octaves, persistence):
'''
Returns a perlin noise function.
octaves is a list of noise functions.
persistence is the persistence value (logarithm of amplitude).
'''
def perlin(x):
total = 0
for i, n in enumerate(octaves):
f = 2 ** i
a = persistence ** i
total += n(x*f) * a
return total
return perlin
def noise2d(noise1d, d):
def noise(x, y):
return noise1d(x + y * d)
return noise
def smooth2d(noise):
def smooth(x, y):
corners = (noise(x-1, y-1)+noise(x+1, y-1)+noise(x-1, y+1)+noise(x+1, y+1)) / 16
sides = (noise(x-1, y)+noise(x+1, y)+noise(x, y-1)+noise(x, y+1)) / 8
center = noise(x, y) / 4
return corners + sides + center
return smooth
def interp2d(noise, interp):
def interpolated(x, y):
fx, ix = math.modf(x)
ix = int(ix)
fy, iy = math.modf(y)
iy = int(iy)
v1 = noise(ix, iy)
v2 = noise(ix+1, iy)
v3 = noise(ix, iy+1)
v4 = noise(ix+1, iy+1)
i1 = interp(v1, v2, fx)
i2 = interp(v3, v4, fx)
return interp(i1, i2, fy)
return interpolated
def perlin2d(octaves, persistence):
def perlin(x, y):
total = 0
for i, n in enumerate(octaves):
f = 2 ** i
a = persistence ** i
total += n(x*f, y*f) * a
return total
return perlin
if __name__ == "__main__":
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment