Worley噪聲的概念與實(shí)現(xiàn)---Unity3D/C#(筆記)
標(biāo)量場(chǎng)和距離場(chǎng)
在了解Worley噪聲之前需要先對(duì)標(biāo)量場(chǎng)和距離場(chǎng)有個(gè)基本概念。
1、標(biāo)量場(chǎng)
場(chǎng)可以理解為一個(gè)關(guān)于空間的函數(shù),函數(shù)的參數(shù)是空間的坐標(biāo),函數(shù)的輸出是一個(gè)標(biāo)量、向量、矩陣或張量。如果輸出是標(biāo)量,則可以稱其為標(biāo)量場(chǎng)。(摘自:游戲開發(fā)技術(shù)雜談11: Worley噪聲 - 知乎 (zhihu.com))
對(duì)于一個(gè)2D空間來說,有了坐標(biāo),有了坐標(biāo)對(duì)應(yīng)的值。就可以將其可視化。首先通過一個(gè)簡(jiǎn)單的函數(shù)對(duì)剛才的距離場(chǎng)建模。
實(shí)施可視化:
Unity3D中新建一個(gè)新建一個(gè)腳本 WorleyView.cs
WorleyView.cs:
新建一個(gè)空對(duì)象,添加WorleyView組件。
創(chuàng)建一個(gè)Image和Button對(duì)象。
賦值。

運(yùn)行游戲,點(diǎn)擊剛剛創(chuàng)建的按鈕,此時(shí)的效果:

2、距離場(chǎng)
距離場(chǎng)是一種特殊的標(biāo)量場(chǎng),相對(duì)于上面測(cè)試的標(biāo)量場(chǎng)來說,距離場(chǎng)多了一個(gè)明確的概念,叫特征點(diǎn)。特征點(diǎn)是散落在空間中的特殊的點(diǎn)。(摘自:游戲開發(fā)技術(shù)雜談11: Worley噪聲 - 知乎 (zhihu.com))
從實(shí)現(xiàn)上來看,標(biāo)量場(chǎng)的特殊點(diǎn)就是原點(diǎn)。
現(xiàn)在實(shí)現(xiàn)四個(gè)特征點(diǎn)的可視化圖形:
在之前的基礎(chǔ)上新增兩個(gè)函數(shù)即可。
修改CreateTex函數(shù):
再次運(yùn)行并點(diǎn)擊,得到:

關(guān)于距離場(chǎng)的計(jì)算,上述代碼的問題主要是其效率過低的問題,如果距離場(chǎng)只有這4個(gè)特征點(diǎn)還好,但是特征點(diǎn)的數(shù)量一旦過多,計(jì)算起來就是一種效率的災(zāi)難了。
其實(shí)對(duì)于空間中的一個(gè)像素點(diǎn),并不需要計(jì)算所有特征點(diǎn)到它的距離然后逐一比較,那些離得明顯比較遠(yuǎn)的部分可以跳過了,只計(jì)算距離比較近的就可以了。所以是如何找到那些比較近的點(diǎn)呢?
Steven·Worley在其論文中的做法是將整個(gè)空間劃分為多個(gè)同等大小的網(wǎng)格,并規(guī)定,在每個(gè)網(wǎng)格中,都有且只有一個(gè)特征點(diǎn)。如下圖所示。

這個(gè)限制讓每個(gè)網(wǎng)格都只有一個(gè)特征點(diǎn)。那么可知,對(duì)于一個(gè)像素點(diǎn)來說,距離它最近的就是周圍九宮格里的點(diǎn),只需要找這9個(gè)點(diǎn)里最近的就行了。
繼續(xù)寫代碼,在原來的基礎(chǔ)上新增三個(gè)函數(shù)。
修改CreateTex函數(shù)。
結(jié)果:

還要支持無縫銜接,修改下腳本:
在腳本首行定義兩個(gè)宏,便于快速切換:
修改 BuildWorleyNoise、DistanceWorley函數(shù):
效果,復(fù)制幾個(gè)進(jìn)行拼接:

下面是整個(gè)腳本: