簡單聊聊 Perlin 噪聲(上篇)

程序開發中總會用到隨機方法,一般的隨機方法雖然通用,但是產生的隨機數又因爲過於"隨機",不適合用來生成平滑連續的隨機數據(譬如自然地形的高度),這個時候我們便需要使用特殊的隨機方法了, Perlin 噪聲便是一種能夠產生平滑(隨機)數值的隨機方法.

Value 噪聲

爲了更容易的理解 Perlin 噪聲,我們先從較簡單的 Value 噪聲看起:

首先我們考慮 一維 情況(即通過一維座標來獲取隨機值),如果我們僅使用一般隨機方法的話,得到的隨機數值是這樣的:

perlin_1_2

可以看到數據雜亂無章,遠不能說是平滑連續,有什麼辦法可以改進呢?

一種樸素的想法就是在整數座標處仍然使用一般隨機方法來生成隨機值,但是對於處在(相鄰)兩個整數座標之間的點(即浮點座標點),則使用線性插值的方式(在這兩個整數座標點對應的隨機值之間線性插值)來生成隨機值,最後得到的隨機數值是這樣的:

perlin_2

可以看到數據比起之前已經平滑連續了不少,但是在整數座標處仍然不夠平滑連續(整數座標處不可導(自然也不連續)),而這是由於我們之前採用了線性插值的方式來生成隨機值造成的,改善的方式也比較明晰,就是改用非線性插值的方式來生成整數座標間的隨機值.

當然,也不是隨便一種非線性插值都可以滿足我們的要求(我們需要該非線性插值在(相鄰)端點(整數座標)處可導並且導數相同(連續)),使用下面的非線性插值方法可以達到我們的目標(公式中的 t t 是原始的線性插值係數, u u v v 則是兩個端點處的隨機值( u u 對應左端點, v v 對應右端點), r r 則是最終的噪聲值):

t = 3 t 2 2 t 3 r = ( 1 t ) u + t v t' = 3t^2 - 2t^3 \\ r = (1 - t')u + t'v

使用上述的方法,我們得到的隨機數值是這樣的:

perlin_3

上述的非線性插值公式還可以進一步改進,基本思想就是使(相鄰)端點(整數座標)處更加"平滑連續"(即在(相鄰)端點(整數座標)處二階導數相同(連續)):

t = 6 t 5 15 t 4 + 10 t 3 r = ( 1 t ) u + t v t' = 6t^5 - 15t^4 + 10t^3 \\ r = (1 - t')u + t'v

基於改進的公式,我們得到的隨機數值是這樣的:

perlin_4

至此,我們便得到了 一維 的 Value 噪聲.

未完待續