【Minecraft】worldedit|generate 探索神奇的噪聲——從原理到應(yīng)用
本專欄教程旨在為mc玩家打開(kāi)一扇新的大門,看完讓你掌握噪聲的原理和基礎(chǔ)運(yùn)用

一、詳解原理
1.1格式

我們現(xiàn)在先只拿perlin噪聲作為例子,其中各個(gè)參數(shù)概念這里不做過(guò)多介紹,這里推薦藍(lán)雞的視頻介紹


1.2函數(shù)概念
在我們寫表達(dá)式時(shí),we給我們提供了很多的函數(shù),形式如 “函數(shù)名()”,比如常用的sqrt()、abs()、atan2()、min()、max()等等,你在括號(hào)中輸入進(jìn)參數(shù),經(jīng)過(guò)這些函數(shù)的運(yùn)算,會(huì)返回一個(gè)結(jié)果,比如min(1,2,3)這個(gè)整體在表達(dá)式中的值就是1(取最小)。
同理,三個(gè)噪聲也是函數(shù),輸入對(duì)應(yīng)參數(shù)(種子,坐標(biāo),頻率等),經(jīng)過(guò)特殊的計(jì)算(想了解具體計(jì)算過(guò)程?我也不知道)返回一個(gè)數(shù)值,返回的范圍是0~1,知道這個(gè)很重要。

1.3生成原理/過(guò)程
具體生成過(guò)程是什么呢?當(dāng)你選擇了一個(gè)選區(qū)之后,輸入的一串的generate指令后,系統(tǒng)會(huì)對(duì)選區(qū)內(nèi)的每個(gè)位置都進(jìn)行一次運(yùn)算,而每個(gè)位置之間有什么差別呢?每個(gè)位置都有自己獨(dú)一無(wú)二的坐標(biāo) (x,y,z),也就是說(shuō),每個(gè)位置是否生成,完全取決于它的坐標(biāo)那三個(gè)數(shù)xyz帶入到表達(dá)式中是否成立,為什么說(shuō)完全取絕于呢?因?yàn)?strong>每個(gè)位置有且僅有坐標(biāo)的"信息"。舉個(gè)例子,比如我們寫一個(gè) x^2+z^2+y^2<1,回車之后,服務(wù)器開(kāi)始對(duì)你的選區(qū)每個(gè)位置進(jìn)行計(jì)算,把每個(gè)位置獨(dú)一無(wú)二的坐標(biāo)帶入進(jìn)去,結(jié)果滿足返回true則生成方塊,不滿足返回false就保持原樣。
知道了生成過(guò)程,我們?cè)倏匆幌聀erlin噪聲的形式
perlin(seed,?x,?y,?z,?frequency,?octaves,?persisence)
我們看到參數(shù)里是有放xyz的地方的,也就是說(shuō),這個(gè)函數(shù)是與我們選區(qū)內(nèi)各個(gè)位置xyz坐標(biāo)信息相關(guān)的,也就是說(shuō)每個(gè)點(diǎn)經(jīng)過(guò)計(jì)算得到的值與x y z都有關(guān)(記好這里,待會(huì)要用)

1.4perlin噪聲特點(diǎn)
程序開(kāi)發(fā)中總會(huì)用到隨機(jī)方法,一般的隨機(jī)方法雖然通用,但是產(chǎn)生的隨機(jī)數(shù)又因?yàn)檫^(guò)于"隨機(jī)",不適合用來(lái)生成平滑連續(xù)的隨機(jī)數(shù)據(jù)(譬如自然地形的高度),這個(gè)時(shí)候我們便需要使用特殊的隨機(jī)方法了, Perlin 噪聲便是一種能夠產(chǎn)生平滑(隨機(jī))數(shù)值的隨機(jī)方法.
我們?yōu)槭裁匆胮erlin噪聲,這要說(shuō)一下perlin噪聲的特點(diǎn),它返回的值是"平滑的",意思是當(dāng)坐標(biāo)相距很近或相鄰,差別不大時(shí),得到的值不會(huì)突變,比如在一定頻率下(x,y,z)返回的值與(x+0.01,y,z)得到的值是很接近的,這使得我們最終得到的結(jié)果是一個(gè)“平滑的”形狀。
如圖


二、變換/應(yīng)用
我會(huì)根據(jù)上面講到的知識(shí)來(lái)講下具體要怎么把perlin噪聲函數(shù)通過(guò)變換添加到我們的表達(dá)式中
2.1限制取值范圍
上圖是一個(gè)最簡(jiǎn)單的應(yīng)用,首先再回顧一下它原理,把坐標(biāo)信息代入返回一個(gè)值,值的范圍為0~1,如果我們僅僅寫一個(gè)?perlin(1,x,y,z,1,1,1) 會(huì)發(fā)生什么

是實(shí)心的,因?yàn)樵趙e的規(guī)則里只要是大于0不包括0,就代表true,生成方塊,而perlin()返回值在0~1間,所以要想使其有意義,我們需要一個(gè)范圍,讓結(jié)果值滿足這個(gè)范圍的的位置生成方塊,不滿足的不生成,這里就要用一個(gè)比較符號(hào)> 或 <,滿足返回true,不滿足返回false,所以我們改改,換成?perlin(1,x,y,z,1,1,1)<0.5,讓值小于0.5的位置滿足表達(dá)式,生成方塊,又因?yàn)閜erlin噪聲是平滑的,所以得到的就是一個(gè)這樣連續(xù)平滑的形狀

這樣就有了區(qū)分,為之后的應(yīng)用打下基礎(chǔ)

2.2調(diào)整坐標(biāo)參數(shù)個(gè)數(shù)
這里再與前面的知識(shí)聯(lián)動(dòng)下,perlin噪聲有三個(gè)參數(shù)位置是用來(lái)放坐標(biāo)信息的,在三維空間中,三個(gè)坐標(biāo)xyz就可以獨(dú)一無(wú)二來(lái)表示一個(gè)位置,那如果我們把其中一個(gè)坐標(biāo)信息給舍棄掉,換成一個(gè)常數(shù),比如我們只要xz,如 ?perlin(1,x,1,z,1,1,1),這么一來(lái),在三維空間中,當(dāng)xz的值一樣時(shí),不同y值之間得到的結(jié)果是沒(méi)有差別的,在游戲里看下

如果只有一個(gè)坐標(biāo)信息x呢?,情況就是,當(dāng)x的值一樣時(shí),不管它的z和y是多少,結(jié)果都是一樣的

由此我們引出一個(gè)具體的應(yīng)用——地形生成,基礎(chǔ)表達(dá)式為?perlin(1,x,1,z,1,1,1)<0.5,如果后面的0.5的取值范圍換成與y相關(guān)的數(shù)呢,比如 y+1<perlin(1,x,1,z,1,1,1),能想象出來(lái)嗎?

當(dāng)y=-1這一層時(shí),此時(shí)表達(dá)式就如同0<perlin(1,x,1,z,1,1,1),幾乎全部滿足,往上增加,perlin()的取值范圍會(huì)變窄,最終當(dāng)y=0時(shí),范圍徹底沒(méi)了,即1<perlin(1,x,1,z,1,1,1)。
簡(jiǎn)化一下就是 y+1<p
如果你明白了,恭喜你學(xué)會(huì)了在取值范圍上做文章的能力,以上的例子只是與y線性相關(guān),如果是y^2、e^y、floor(y)會(huì)是什么樣的效果,但要注意的是你要讓這個(gè)f(y)中y在-1~1中得到的值域與perlin噪聲的值域相交,這樣才會(huì)有意義。我再舉個(gè)例子

這里加了-c,就使用世界坐標(biāo)的尺度,每一格代表1,所以對(duì)應(yīng)的頻率也要改變(選區(qū)大小為100*100*100)

2.3對(duì)參數(shù)進(jìn)行變換/替換
perlin噪聲標(biāo)準(zhǔn)形式形如 perlin(1,x,y,z,1,1,1),如果我們對(duì)內(nèi)部的坐標(biāo)參數(shù)進(jìn)行一些變換,如拉伸,收縮
為了更好的展示紋理的應(yīng)用,我這里只在一個(gè)水平面上生成,此時(shí)的y的存在就可有可無(wú)了

不做變換直接是

我們對(duì)它在z軸上拉伸變換一下,即讓z除以一個(gè)大于1的數(shù)為拉伸

若z乘以一個(gè)大于1的數(shù)則為收縮,此時(shí)視覺(jué)上就是x軸在拉伸

適當(dāng)調(diào)整頻率、取值范圍和其他參數(shù),我們就會(huì)得到木制紋理(當(dāng)然也可以用在其他場(chǎng)景)

接下來(lái)我要講的是替換,標(biāo)準(zhǔn)格式的perlin()是與x,y,z三個(gè)相關(guān)的,如果我們把其中一個(gè)比如y替換成sqrt(x^2+z^2)會(huì)發(fā)生什么

sqrt(x^2+z^2)代表的是什么?是每個(gè)點(diǎn)與(0,0)的距離,我們稱這個(gè)距離格式稱為“歐氏距離”,所以在選區(qū)內(nèi)的每個(gè)位置要帶入perlin噪聲的值就成了x,z和與原點(diǎn)的距離,即這個(gè)生成圖案與x有關(guān),與z有關(guān),也與到原點(diǎn)的歐式距離有關(guān)
如果我們只留一個(gè)sqrt(x^2+z^2)會(huì)發(fā)生什么?

perlin()的值只與到原點(diǎn)的距離有關(guān),到原點(diǎn)的距離一樣的位置的取得的值就是一樣,就會(huì)呈現(xiàn)一環(huán)一環(huán)的紋理
這里插入一個(gè)知識(shí),有歐氏距離sqrt(x^2+z^2),還有街區(qū)距離abs(x)+abs(z)和棋盤距離max(abs(x),abs(z)),感興趣的可以去搜搜
棋盤距離

街區(qū)距離

當(dāng)然,我們可以在這三個(gè)位置填入任何變量,這取決于你想要的效果與什么量有關(guān)
再插入一個(gè)重要的技巧,你要按perlin的值上色的話,要把不同的值分開(kāi),用data=p*n%n,n是我把perlin的范圍擴(kuò)展了一下,如果n為5,那么范圍就變成了0~5,然后再用5對(duì)其取余,讓不同的值得到不同的data,就把perlin的值按大小分成了5個(gè)
如果你想要一個(gè)紋理與極角atan2(x,z)有關(guān),即想要極角一樣位置的perlin()的值一樣,那就

這也就是我動(dòng)態(tài)里煙花的基本原理,發(fā)散形的形狀
別忘了,這些只是在平面上的效果,如果按照前面做地形的原理來(lái)做個(gè)地形或什么,效果會(huì)更好


2.4噪聲混合/疊加
這里講的是如何把不同的噪聲怎么結(jié)合,這個(gè)原理類似于ps里的圖層疊加的原理
如果你耐心讀上圖的指令的話,會(huì)發(fā)現(xiàn)我加了一個(gè)L=(1/(1+e^(5*(sqrt(x^2+z^2)-0.5)))),于是原本的 y+1<p?的形式就變成了 y+1<p*L 。這個(gè)是為了與原始的地形相乘,相乘這個(gè)操作就可以把原始地形進(jìn)行一個(gè)調(diào)整,即改變/限制了perlin()的輸出,我們來(lái)單看這個(gè)表達(dá)式會(huì)生成什么樣的

可以看出我讓邊緣的值一乘變得和小,越往中心就越大,最中心的值就是1,單獨(dú)在平面的形式為

這個(gè)函數(shù)應(yīng)用場(chǎng)景很多的,順便再推薦幾個(gè)我常用的幾個(gè)函數(shù),如 指數(shù)函數(shù)e^x,e^(-x^2),冪函數(shù),x^2,x^8,還有個(gè)雙曲余弦函數(shù),cosh(x/a)*a,這個(gè)是懸鏈線的函數(shù),用來(lái)做自然的懸鏈效果就用這個(gè),把它倒轉(zhuǎn)過(guò)來(lái)就是個(gè)最科學(xué)的拱形
回到噪聲的主題,除了與一個(gè)固定的函數(shù)來(lái)相乘,還可以與另一個(gè)噪聲相乘,比如兩個(gè)頻率不同的噪聲來(lái)相乘,會(huì)得到更豐富的地形,讓它有一個(gè)基礎(chǔ)的輪廓,不會(huì)顯得太規(guī)整

這個(gè)技巧在我的另一個(gè)動(dòng)態(tài)有展示

//deform -c x=3*floor(x/3);
看到了吧,結(jié)合以上說(shuō)的兩種辦法,連個(gè)噪聲相乘,又與一個(gè)限制函數(shù)L相乘,簡(jiǎn)化之后就是?y+1<p1*p2*L
另外,還可以相加,很簡(jiǎn)單,就不放圖了y+1<p1+p2
取交集部分,y+1<min(p1,p2)?
取并集,y+1<max(p1,p2)
所有都要注意變換結(jié)合后的值域是否變化,必要時(shí)可以乘一個(gè)常數(shù)來(lái)整體調(diào)整
我這里只能簡(jiǎn)單告訴方法,具體實(shí)踐還要靠自己慢慢打磨。

2.5其他應(yīng)用
因?yàn)閜erlin噪聲函數(shù)會(huì)返回一個(gè)隨機(jī)但平滑的數(shù)值,因此可以把他應(yīng)用到各種場(chǎng)合,不僅僅地形,我會(huì)發(fā)一些日常的動(dòng)態(tài)來(lái)展示,可以翻翻
比如我可以在磚塊紋理表達(dá)式的基礎(chǔ)上加上噪聲,使墻面更不規(guī)則


我還可以用基礎(chǔ)的拉伸變換和替換做出這樣的墨跡效果


在y+1<p*L中,你還可以直接在L中添加p,來(lái)與噪聲相匹配,如

本來(lái)是1-sqrt(x^2+z^2),為了讓1在一段范圍內(nèi)上下波動(dòng),所以把p的0~1的范圍改成范圍的中心是1的一個(gè)形式,就比如(p+1)/2范圍為0.5~1.5

對(duì)了,你還可以把這些噪聲進(jìn)行嵌套

先在p1里把y軸壓縮(y*8),形成水平的條紋,再用另一個(gè)噪聲p2,對(duì)其進(jìn)行相加,使條紋不再只是水平

其實(shí)有個(gè)東西忘記提了,就是噪聲中的其他參數(shù)也是可以加坐標(biāo)信息的,比如讓一座山的頻率從z的一端到另一端逐漸增大——2*e^(1-0.5*z)


還比如我在比賽中做的右下角的海草,就把噪聲放到了rotate里面,讓他有一個(gè)隨機(jī)扭曲的效果,指令長(zhǎng)度直接到了聊天文本上限,這還是精減過(guò)的


一條滿意的指令背后,有一個(gè)很長(zhǎng)的打磨過(guò)程,這個(gè)海草就經(jīng)歷了這么多次的修改迭代


所以做這些東西要多思考,發(fā)散思維,發(fā)揮想象,必要時(shí)上網(wǎng)查查資料,你也可以!
這個(gè)坑算是填上了,接下來(lái)的想法是研究研究megabuf