從雪花到宇宙 —— 用數(shù)據(jù)包自定義維度(二)
前面我們就很頻繁地提到了一個詞:噪聲。并且,我們?yōu)榱撕啽闫鹨?,在第一章?jié)的維度中實際上并沒有使用任何噪聲相關(guān)的知識,相反,噪聲被單獨分離了出來,足見噪聲的復(fù)雜性和重要性。
這一章節(jié)中可能不會講解太多的實際內(nèi)容,我們更多的會偏向理論一些,講解Minecraft地形是如何借助噪聲算法誕生的。在下一章節(jié)中,我們才會講解噪聲在數(shù)據(jù)包中的應(yīng)用,即密度函數(shù)和噪聲設(shè)置。
從雪花點開始
首先想想一下我們應(yīng)該如何生成一個地形。首先確立一個三維坐標系,為了生成一個隨機地形,最簡單的方式就是,對于每一個x,z值對應(yīng)的位置,我們直接使用一個隨機數(shù)作為地形的高度。這樣,我們得到的地形大概是這個樣子的。

看起來就像……老電視機上的雪花噪點一樣。點與點之間的地形毫無連續(xù)性,右邊方塊的地形可能是y=0,左邊可能就變成了y=114的沖天柱子。這顯然不是我們想要的地形,那么怎么讓地形在有隨機性的同時又保留連續(xù)性和光滑性呢?
上世紀八十年代,Ken Perlin為了在電影TRON中模擬隨機效果,提出了一種隨機算法,通過平滑插值的方式,讓噪聲更加平滑自然。

可以看出,如果我們使用柏林噪聲,圖像就變得平滑了許多,也就意味著我們的地形變得更加的平滑,也就更加趨近于現(xiàn)實。
現(xiàn)在考慮另一個問題。雖然我們現(xiàn)在能生成平滑的噪聲,但是噪聲太平滑了,很難產(chǎn)生Minecraft世界中需要的各種細節(jié)。為了簡潔起見,我們用正弦函數(shù)的圖像來代替我們的噪聲函數(shù)的起伏:

這是一個簡單的y=sinx的函數(shù)。和我們的噪聲函數(shù)一樣,平滑,有起伏。但是它也同樣不能產(chǎn)生小的細節(jié)。現(xiàn)在我們稍微疊加一下:

綠色的還是sinx,橙色的是0.5sin2x,然后我們把這兩個函數(shù)加起來,得到紫色的函數(shù)圖像??梢钥闯鰜?,波峰波谷的基本形狀依然是存在的,但是加了一些起伏的小細節(jié)。
讓我們多加一些類似的函數(shù):

現(xiàn)在是sinx+0.5sin2x+0.25sin4x+0.125sin8x。依然只是簡單的疊加,但是看起來和現(xiàn)實中的地形很相似了。如果我們把正弦函數(shù)換成柏林噪聲,然后進行相同方式的疊加,我們就可以得到有大量細節(jié)的地形了!

數(shù)據(jù)包中的噪聲
數(shù)據(jù)包的噪聲儲存在data/<命名空間>/noise/<噪聲名稱>.json
中。它的格式是這樣的:
wiki似乎缺少這方面的資料,我只能通過自己有限的學識進行一些猜測。firstOctave
鍵大概就是主噪聲的頻率(周期),amplitudes
大概就是設(shè)置噪聲的振幅,列表則對應(yīng)了上文中疊加正弦函數(shù)一樣的疊加過程,而每一個整數(shù)值就是要疊加的噪聲的振幅,整數(shù)值對應(yīng)的位置則決定了它代表的噪聲的頻率。例如:
首先我們決定了噪聲的主頻率是-5,那么整數(shù)列表中從上到下依次五個值,它們對應(yīng)的噪聲倍頻則是-5、-4、-3、-2、-1,而振幅則都是1。值得注意的是,實際上疊加的時候的振幅應(yīng)該是類似1、0.5、0.25的關(guān)系。至于為什么會這樣做,我也不知道(嗚嗚嗚
噪聲的json文件可能會很費解,但是幸運的是,噪聲 生成器 – Minecraft 1.18, 1.19, 1.20 (misode.github.io)可以幫助你實時預(yù)覽噪聲的形狀,你只需要大致明白噪聲的原理,就可以隨心調(diào)整參數(shù),直到你滿意為止。原版同時也提供了很多寫好的噪聲函數(shù),你也可以直接調(diào)用原版的噪聲函數(shù),它們都放在了原版數(shù)據(jù)包文件夾下對應(yīng)的位置(和你的數(shù)據(jù)包一樣的位置)
總結(jié)
噪聲是一切的基礎(chǔ)。Minecraft世界生成中,噪聲的影子隨處可見,地形起伏,生物群系的生成,都離開不了噪聲。在下一章中,我們將會繼續(xù)從噪聲出發(fā),講解噪聲是如何生成一個豐富多彩的地形的。
筆者學識有限,對于噪聲的內(nèi)容自己也只能說出大概思路,如果有錯誤或者疏忽的地方,還望讀者不吝指正。