2017-02-27 21 views
1

我已經採取了Wikipedia Perlin Noise Algorithm並實現它在Python,這裏是代碼:Perlin雜文物

import random 
import math 
from PIL import Image 
from decimal import Decimal 


IMAGE_SIZE = 200 
PERLIN_RESOLUTION = 10 
GRADIENT = [] 


for x in range(PERLIN_RESOLUTION + 1): 
    GRADIENT.append([]) 
    for y in range(PERLIN_RESOLUTION + 1): 
     angle = random.random() * 2 * math.pi 
     vector = (
      Decimal(math.cos(angle)), 
      Decimal(math.sin(angle)) 
     ) 
     GRADIENT[x].append(vector) 


def lerp(a0, a1, w): 
    return (1 - w)*a0 + w*a1 


def dotGridGradient(ix, iy, x, y): 

    dx = x - Decimal(ix) 
    dy = y - Decimal(iy) 

    return (dx*GRADIENT[iy][ix][0] + dy*GRADIENT[iy][ix][1]) 


def perlin(x, y): 
    if x > 0.0: 
     x0 = int(x) 
    else: 
     x0 = int(x) - 1 
    x1 = x0 + 1 
    if y > 0.0: 
     y0 = int(y) 
    else: 
     y0 = int(y) - 1 
    y1 = y0 + 1 

    sx = x - Decimal(x0) 
    sy = y - Decimal(y0) 

    n0 = dotGridGradient(x0, y0, x, y) 
    n1 = dotGridGradient(x1, y0, x, y) 
    ix0 = lerp(n0, n1, sx) 
    n0 = dotGridGradient(x0, y1, x, y) 
    n1 = dotGridGradient(x1, y1, x, y) 
    ix1 = lerp(n0, n1, sx) 
    value = lerp(ix0, ix1, sy) 

    return value 


image = Image.new('RGB', (IMAGE_SIZE, IMAGE_SIZE)) 
pixels = image.load() 
for i in range(IMAGE_SIZE): 
    x = Decimal(i)/IMAGE_SIZE 
    for j in range(IMAGE_SIZE): 
     y = Decimal(j)/IMAGE_SIZE 
     value = perlin(x * 10, y * 10) 
     greyscale = (value + 1) * 255/2 
     pixels[i, j] = (greyscale, greyscale, greyscale) 
image.save('artifacts.png', 'PNG') 

這裏是由腳本生成結果圖像:

Perlin with artifacts

我必須在這裏丟失一些東西,你可以非常清楚地看到頂點。任何人都可以讓我知道哪裏出了問題?

回答

2

您需要使用smoothstep而不是線性插值。

def smoothstep(a0, a1, w): 
    value = w*w*w*(w*(w*6 - 15) + 10) 
    return a0 + value*(a1 - a0) 
+0

嘿,非常感謝您的回覆,WhatEvDev。我試了一下,它似乎很好。我想接受你的答案,但在此之前,你可以解釋爲什麼這個函數更好(以及爲什麼很多示例算法在線似乎使用lerp,如維基百科)。 –

+1

線性插值用作示例,因爲它是最簡單的插值('value = w')。如果你用lerp使用一維珀林噪聲,你將得到多邊形曲線。 爲了得到平滑的結果,您需要在點之間平滑插值。爲此,您需要一個在0和1處具有零階一階導數(也可能是二階導數)的函數。如果您將一階柏林噪聲用於smoothstep,您將獲得平滑曲線。 – WhatEvDev