Perlin Noise Experiments (1D)

Import the necessary libraries

In [1]:
from random import random, randrange
from math import floor
from matplotlib import pyplot as plt

Define the global constants

In [2]:
TABLE_SIZE = 255

Initialize the random gradient vectors

In [3]:
gradients = []
permutations = []
for i in range( TABLE_SIZE ):
    gradients.append( random() * 2 - 1 )
    permutations.append( i )

Create the uniformly distributed permutation table

In [4]:
for i in range( TABLE_SIZE ):
    t = permutations[ i ]
    idx = randrange( TABLE_SIZE )
    permutations[ i ] = permutations[ idx ]
    permutations[ idx ] = t

print( permutations )

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

Define the hash function

In [5]:
def hash_pos( x ):
    return permutations[ x % TABLE_SIZE ]

Define smoothing function

In [6]:
def smooth_step( x ):
    return ( x ** 3 ) * ( x * (x * 6 - 15 ) + 10 )

Define linear interpolation function

In [7]:
def linterpolate( a, b, weight ):
    return a + weight * ( b - a )

Define function for calculating Perlin noise at a point

In [8]:
def perlin_at( x ):
    lx = floor( x ) 
    rx = ( lx + 1 )
    xd = x - floor( x )
    weight = smooth_step( xd )
    l = gradients[ hash_pos( lx ) ]
    r = gradients[ hash_pos( rx ) ]
    ld = xd
    rd = xd - 1
    return linterpolate( ld * l, rd * r, weight )

Visualize the Perlin noise by plotting it

In [9]:
STEP = .23
RANGE = 15
HEIGHT = 1.5
STEPS = floor( RANGE / STEP )
x = []
y = []
for i in range( STEPS ):
    t = i * STEP
    x.append( t )
    y.append( perlin_at( t ) )
plt.plot( x, y )
plt.ylim( -HEIGHT, HEIGHT )
plt.show()