Perlin 噪聲


如果想產生一條隨機的曲線,最基本的想法是利用 random 函式,在每個 x 處產生一個隨機的 y 值吧!不過,這樣的線連接起來後,比較像個折線,不連續而且無規律:

這邊介紹一下 beginShapevertexendShape,這三個函式配合起來,可用來繪製多邊形,只不過這邊將其中三個邊貼在畫布的邊緣,看來就像是繪製多線段,然而又可以有不同於背景的填滿效果,beginShapevertexendShape 也可以用來繪製多線段,這之後再來談。

random 產生的值不會是連續的,想想看,自然界有許多看似隨機,然而卻又連續的現象,例如岳崚起伏,看似不規則,然而高低之間又有一定的連續性,如果想要在程式中模擬這種隨機又連續的現象,可以考慮 Perlin 噪聲。

來看看一維 Perlin 噪聲的基本原理,你可以在每個整數 x 點產生一個隨機值,然而這個隨機值並不作為 y 值,而是作為穿越該點的一條線之斜率,而該線是曲線的切線由增往減或由減往增的轉折點:

Perlin 噪聲

曲線穿過每個整數 x 點,因此該點 y 值是 0,兩個 x 點間的 y 值,透過 Ken Perlin 設計的內插函式計算而得,如果你使用 p5.js,知道這些就夠了,因為 p5.js 的 noise 函式就實現了 Perlin 噪聲,若對如何插值有興趣,可以參考〈Simplex noise demystified〉,上圖其實也是從該文件中取得。

p5.js 的 noise,會產生 0 到 1 的值,記得,每個整數 x 處的值會是 0,你必須使用整數間的小數來計算,來看看怎麼使用:

這邊透過 map 函式轉換,將 x 的範圍 0 到 width,對應至 0 到 width / 100,這樣就會取得小數,簡單來說,你會提供 0.01、0.02 … 3 的值給 noise 函式,雖然說這邊直接寫 let nx = x / 100 也可以,不過順便認識個新函式也不錯,若你的起始範圍對應不為 0 時,使用 map 會比較方便。

一維的 Perlin 噪聲通常可以作為 y 值,二維的 Perlin 噪聲,通常可作為高度、灰階度或彩度,例如營造雲霧效果:

如果用來 3D 建模,可以建立用來建立自然地形(下圖為我用自己寫的二維 Perlin 噪聲在 OpenSCAD 建模的效果):

Perlin 噪聲

p5.js 官方的範例文件中,有個 Noise Wave,運用了二維的 Perlin 噪聲,創造出海浪不斷變化的感覺,來稍加整理一下該範例的程式碼:

範例中的 xoffyoff 變化令人好奇,其實 xoffyoff 建立了一個平面範圍,如果你將這個範圍表現為 3D 地形圖,效果就如方才 OpenSCAD 中的地形圖,只不過這邊在 yoff 處切下一刀,然後畫在 2D 的畫布上,才會有海浪不斷變化的感覺。

三維的 Perlin 噪聲呢?三維指定了 (x, y, z) 產生的噪聲值可以應用在哪?通常可以視為透明度,或者是密度,例如在 Minecraft 中,運用了三維 Perlin 噪聲,在噪聲值大於某個值時才產生方塊,這就創造出自然洞穴的效果。

如果是用來作為透明度,想像有個掃描平面,由低往高掃描,將每個透明度值轉為彩度值會如何呢?

這只是 Perlin 噪聲的一些應用,想怎麼運用這些噪聲,就看你有多少創意了!