Created
December 1, 2017 22:01
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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