I have been implementing a perlin noice generator in python. It works pretty well except for clearly visible lines in the result.
The problem seems to be related to where i switch between gradients in X-direction.
Here is the code:
from random import randint, seed
from PIL import Image
from numpy import asarray, interp, uint8
seed(1)
gradients = []
for x in range(20):
gradients.append([])
for y in range(20):
gradients[x].append([randint(-1,1), randint(-1,1)])
def getInfluenceValue(x,y,Xgrad,Ygrad):
return ((gradients[Xgrad][Ygrad][0] * (x-Xgrad)) + (gradients[Xgrad][Ygrad][1]*(y-Ygrad)))
def lerp(v0,v1,t):
return (1 - t) * v0 + t * v1;
def fade(t):
return 3*pow(t,2) - 2*pow(t,3)
def perlin(x, y):
X0 = int(x)
Y0 = int(y)
X1 = X0+1
Y1 = Y0+1
sx = fade(float(x) - float(X0));
sy = fade(float(y) - float(Y0));
topLeftDot = getInfluenceValue(x,y,X0,Y1)
topRightDot = getInfluenceValue(x,y,X1,Y1)
bottomLeftDot = getInfluenceValue(x,y,X0,Y0)
bottomRightDot = getInfluenceValue(x,y,X1,Y0)
return lerp(lerp(topLeftDot, topRightDot, sx), lerp(bottomLeftDot, bottomRightDot, sx), sy)
tmp_list = []
for x in range(1000):
tmp_list.append([])
for y in range(1000):
tmp_list[x].append(perlin(x/100.0, y/100.0))
data = asarray(tmp_list)
rescaled = interp(data, (data.min(), data.max()), (0, 255)).astype(uint8)
Image.fromarray(rescaled).save('test.png')
Here is the result:
I have tried replacing the lerp function and i have used other fade functions. But the problem remains. What's going on here?
PS. I have seen other questions on stackoverflow regarding "blocky" results in perlin noise generation, but since this result only seem to be "blocky" in 1 direction/dimension, i think the problem is unrelated to those questions.