2017-02-09 6 views
4

Я пытаюсь произвести 2D Перлин шума с использованием NumPy, но вместо того, чтобы что-то гладком я получаю это:Производство 2D Перлин шума с NumPy

my broken perlin noise, with ugly squares everywhere

Конечно, я перепутать свои размеры где-то , вероятно, когда я совмещаю четыре градиента ... Но я не могу найти его, и мой мозг тает прямо сейчас. Кто-нибудь может помочь мне определить проблему?

Во всяком случае, вот код:

%matplotlib inline 
import numpy as np 
import matplotlib.pyplot as plt 

def perlin(x,y,seed=0): 
    # permutation table 
    np.random.seed(seed) 
    p = np.arange(256,dtype=int) 
    np.random.shuffle(p) 
    p = np.stack([p,p]).flatten() 
    # coordinates of the first corner 
    xi = x.astype(int) 
    yi = y.astype(int) 
    # internal coordinates 
    xf = x - xi 
    yf = y - yi 
    # fade factors 
    u = fade(xf) 
    v = fade(yf) 
    # noise components 
    n00 = gradient(p[p[xi]+yi],xf,yf) 
    n01 = gradient(p[p[xi]+yi+1],xf,yf-1) 
    n11 = gradient(p[p[xi+1]+yi+1],xf-1,yf-1) 
    n10 = gradient(p[p[xi+1]+yi],xf-1,yf) 
    # combine noises 
    x1 = lerp(n00,n10,u) 
    x2 = lerp(n10,n11,u) 
    return lerp(x2,x1,v) 

def lerp(a,b,x): 
    "linear interpolation" 
    return a + x * (b-a) 

def fade(t): 
    "6t^5 - 15t^4 + 10t^3" 
    return 6 * t**5 - 15 * t**4 + 10 * t**3 

def gradient(h,x,y): 
    "grad converts h to the right gradient vector and return the dot product with (x,y)" 
    vectors = np.array([[0,1],[0,-1],[1,0],[-1,0]]) 
    g = vectors[h%4] 
    return g[:,:,0] * x + g[:,:,1] * y 

lin = np.linspace(0,5,100,endpoint=False) 
y,x = np.meshgrid(lin,lin) 

plt.imshow(perlin(x,y,seed=0)) 
+3

ваша интерполяция использует угол 'n10' дважды и опускает 'n01' –

+0

Хорошая добыча! После этого я сделал две другие поправки, и теперь это работает ... редактирование оригинального сообщения. – tomtom

ответ

3

Благодаря Paul Panzer и спокойной ночи сна он работает сейчас ...

def perlin(x,y,seed=0): 
    # permutation table 
    np.random.seed(seed) 
    p = np.arange(256,dtype=int) 
    np.random.shuffle(p) 
    p = np.stack([p,p]).flatten() 
    # coordinates of the top-left 
    xi = x.astype(int) 
    yi = y.astype(int) 
    # internal coordinates 
    xf = x - xi 
    yf = y - yi 
    # fade factors 
    u = fade(xf) 
    v = fade(yf) 
    # noise components 
    n00 = gradient(p[p[xi]+yi],xf,yf) 
    n01 = gradient(p[p[xi]+yi+1],xf,yf-1) 
    n11 = gradient(p[p[xi+1]+yi+1],xf-1,yf-1) 
    n10 = gradient(p[p[xi+1]+yi],xf-1,yf) 
    # combine noises 
    x1 = lerp(n00,n10,u) 
    x2 = lerp(n01,n11,u) # FIX1: I was using n10 instead of n01 
    return lerp(x1,x2,v) # FIX2: I also had to reverse x1 and x2 here 

def lerp(a,b,x): 
    "linear interpolation" 
    return a + x * (b-a) 

def fade(t): 
    "6t^5 - 15t^4 + 10t^3" 
    return 6 * t**5 - 15 * t**4 + 10 * t**3 

def gradient(h,x,y): 
    "grad converts h to the right gradient vector and return the dot product with (x,y)" 
    vectors = np.array([[0,1],[0,-1],[1,0],[-1,0]]) 
    g = vectors[h%4] 
    return g[:,:,0] * x + g[:,:,1] * y 

lin = np.linspace(0,5,100,endpoint=False) 
x,y = np.meshgrid(lin,lin) # FIX3: I thought I had to invert x and y here but it was a mistake 

plt.imshow(perlin(x,y,seed=2),origin='upper')