噪聲算法如何避免成為白噪聲的
能直接看懂下面代碼塊中的博客是最好的。
本文中的代碼是對這篇博客中引用的官方C++代碼在Unity中的實(shí)現(xiàn),本文最后會貼出來。
我對噪聲的理解原理就是“一個頂點(diǎn)延伸出去一條向量,對這條向量做插值?!?/p>
我這里解釋一下噪聲的“規(guī)律”:
噪聲代碼中的Fade平滑是用一個計(jì)算數(shù)學(xué)函數(shù)f(x)的方法,這個函數(shù)的要求是對受限的傳入值,返回[0,1]的結(jié)果。
因?yàn)閘erp插值需要的只有[0,1]這個區(qū)間。
在官方算法中,表現(xiàn)為: 對參數(shù)取小數(shù)部分,使用一個定義域為[0,1]時,值域為[0,1]的函數(shù)。
對于函數(shù)的選取有三個要求:f(0)=0、f(0.5)=0.5、f(1)=1,官方使用的是第三個公式:
???

以上解釋的是平滑參數(shù)部分。

接下來說明梯度與頂點(diǎn)組。
博客代碼使用Vextor3[]記錄備選梯度,使用隨機(jī)從備選梯度中抽取梯度為頂點(diǎn)賦值梯度,由此,其噪聲圖實(shí)現(xiàn)了隨機(jī)。
上方代碼中的頂點(diǎn)是一個三維數(shù)組記錄的,頂點(diǎn)組可以認(rèn)為是一個取樣樣本,或者通俗的說是Minecraft一個種子會得到相同的地圖一樣,只要是相同的頂點(diǎn)組,使用相同的算法就能得出一樣的結(jié)果。
這是官方給出的遍歷,i、j受限于Hash梯度表的Lenght、i、j+=?則取決于你希望生成噪聲的像素大小,官方這個就是生成一個400*400像素的噪聲圖。
而官方噪聲的隨機(jī)就來自于梯度,之后你們運(yùn)行代碼,如果不隨機(jī)梯度或修改取樣間隔,那么噪聲圖是一模一樣的。
也就是說,通過隨機(jī)參數(shù)構(gòu)建了一個三維n*n*n空間,世界的頂點(diǎn)都具有一定的“力量”,對非頂點(diǎn)區(qū)域有,總的來說越遠(yuǎn)越弱的掌控力。
而二維噪聲就是對這個空間的部分區(qū)域的切片取樣。

說明一些細(xì)節(jié):
為什么要與255?因?yàn)樵谙旅娴乃惴ㄖ杏?/p>
在極限狀態(tài)下,會有
????index = 255 + 255 + 1 = 511,正好是Length為512的數(shù)組的最大索引。
各種算法都要或多或少的比 按像素生成噪聲圖的main語句中的i、j的結(jié)束值 多一些頂點(diǎn)。
又比如博客中的教學(xué)程序,聲明了25的頂點(diǎn),但for循環(huán)應(yīng)該截止在24。
Length為512的數(shù)組。

這里對插值的參數(shù)們進(jìn)行代入法。
我們采用for循環(huán)到16的頂點(diǎn),期望像素為512x512。
紋素就是16/512=0.03125

選取像素點(diǎn)115,115,對應(yīng)x,y值是3.59375。
由于是2維圖對3維采樣,因此z定值即可,這里采用7.8

選取像素點(diǎn)118,115,對應(yīng)x值是3.6875,y值是3.59375。
由于是2維圖對3維采樣,因此z定值即可,這里采用7.8
對于在同一頂點(diǎn)區(qū)間的兩個像素點(diǎn),他們的插值參數(shù)u、v、w差不多,取用的梯度Hash也是相同的,這樣就能很大程度上保證兩個像素獲得的灰度值差不多,就是非白噪聲了。
對噪聲(n+1)/2能更好的將值限制在(0,1),小于零黑大于1白,少量的極大值也是噪聲的一部分。