Minecraft 裏的學問(二):地圖爲什麼看起來那麼自然

Minecraft 的世界是用一個 64 位數字算出來的。理論上能生成的世界有 2 的 64 次方種,也就是 18 後面跟着 18 個零。而遊戲文件裏沒存下任何一座山、任何一條河,它只存了一個種子,地形是運行時現算的。

現算出來的東西,爲什麼看起來像真的?

這篇講三件事。純隨機會生成什麼,噪聲怎麼做到既隨機又連續,以及爲什麼一層還不夠。

先看看純隨機會生成什麼

假設你寫一行代碼,給地圖上每個點隨機取一個高度。結果不會像地形,會像雪花屏:每個點跟旁邊那個點沒有任何關係,東邊是尖峯,西邊緊接着懸崖。

問題就出在沒有關係上。真實地形是有關係的:一座山不會憑空冒出來,它有山坡、有山腳,山腳還要連着平地。相鄰的地方必然相似,越遠才越不相似。這在數學上叫相關性,或者說連續性。

純隨機(白噪聲)缺的正是這個。它每個點都是獨立的,所以它只有噪點,沒有結構。

噪聲解決的就是這件事

Perlin 噪聲的做法說穿了不復雜。它把整個空間切成一張網格,在每個格點上隨機放一個方向,也就是一個向量。然後對網格中間任意一點,取它所在格子的四個角,把每個角的向量分別和「從這個角指向該點」的向量做一個點積,得到四個數。

這四個數還連不到一起,所以最後一步是插值:按離四個角的遠近,把四個數平滑地混成一個。

這一步很關鍵。用來混的那條曲線不是在格點處簡單銜接,而是保證在格點上的變化率爲零——用到的是一條五次曲線。所以噪聲取出來的值,走到格子邊界也不會突然跳一下,是真正連續的。

結果是這麼一幅圖:每個格子中心隨機,但格子之間平滑過渡,永遠不會斷開。這就是爲什麼用它算出來的地形不會出現雪花屏。

一層不夠,於是有了疊

如果只用一層噪聲當地形,你會得到一個像麪糰一樣的世界:到處是緩坡,圓滾滾的,說不上難看,但沒有山的銳利感,也沒有細碎的岩石。

因爲一層噪聲只提供一個尺度,它的變化都是同一個大小的。

真實的山水不是這樣。真實的地形是很多尺度疊在一起的:綿延幾十公里的山脈,幾公里的山脊,幾百米的山頭,幾十米的岩石和碎石。它們不是一個東西,是層層套着的。

所以下一步是把好幾層疊加起來,疊的時候有兩個固定動作。

每往上疊一層,把頻率翻倍,也就是噪聲的疏密變成上一層的兩倍;同時把振幅減半,也就是這層的起伏高度只有上一層的一半。

這樣一來,第一層負責大輪廓,撐出山脈和盆地;第二層負責中等起伏,在山坡上刻出山脊和溝谷;第三層再往上添碎石和坑窪。第三層之上還可以繼續疊,直到細到你看不見。

加起來的結果就是那種眼熟的地形:遠看有山勢,走近有坡,再近有石頭和坑。

這兩個參數在圖形學裏有名字:振幅每層減多少叫持久度,一般取一半;頻率每層翻多少倍叫間隙度,一般取兩倍。調整這兩個數,就能讓地形從平緩變成陡峭,從圓潤變成崎嶇。這也是爲什麼不同的遊戲、不同的地圖,地形風格能差那麼多。

Minecraft 具體是怎麼用的

原版地形用的是分形的 Perlin 噪聲。其中有兩個噪聲分工:一個三維噪聲決定地下的豎直結構,另一個二維噪聲當高度圖,決定地表的起伏。

1.18 之後這套系統更細了。生物羣系不再只用溫度和溼度兩個參數判斷,而是六個。其中大陸性決定這裏是海洋、海岸還是內陸,侵蝕度決定這裏平坦還是多山。每個參數都是獨立算出來的噪聲值。

算完之後還有一步:把噪聲值通過一條樣條曲線映射到具體高度。這麼做是爲了讓地形出現突變——比如陡崖、臺地這類自然界裏真實存在的例外。光靠疊加,出來的地形會太均勻。

現在更常見的實現用單純形噪聲,也是 Perlin 發明的,只改了網格形狀,好在高維上算得快些。思路一樣。

發明這套東西的人

Perlin 噪聲是 Ken Perlin 在 1983 年做出來的。當時他在一家動畫公司,接手迪士尼電影《Tron》的活,對當時電影畫面裏的機械感不滿意,於是自己寫了一套生成自然紋理的辦法。

1985 年他在圖形學頂會 SIGGRAPH 上發表了論文。1997 年,美國電影藝術與科學學院給他頒了技術成就獎,也就是奧斯卡的技術獎項,理由是這套噪聲讓計算機生成的自然表面變得可信。

他沒有給這個算法申請專利。

從 1983 年到現在,電影裏的雲、火、煙,遊戲裏的山川、礦洞,用的是同一套東西。你在 Minecraft 裏看到的那座山,和幾十年前科幻片裏那片雲,出自同一個函數。

更多遊戲資訊請關註:電玩幫遊戲資訊專區

電玩幫圖文攻略 www.vgover.com