最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于C++實現(xiàn)柏林噪聲算法(Perlin?Noise)

 更新時間:2023年03月31日 10:28:18   作者:寡人正在Coding  
Perlin噪聲(Perlin?noise,又稱為柏林噪聲)指由Ken?Perlin發(fā)明的自然噪聲生成算法,具有在函數(shù)上的連續(xù)性,并可在多次調(diào)用時給出一致的數(shù)值。本文將用C++實現(xiàn)柏林噪聲算法,感興趣的可以了解一下

概述

引述維基百科的介紹:

Perlin噪聲(Perlin noise,又稱為柏林噪聲)指由Ken Perlin發(fā)明的自然噪聲生成算法,具有在函數(shù)上的連續(xù)性,并可在多次調(diào)用時給出一致的數(shù)值。 在電子游戲領(lǐng)域中可以透過使用Perlin噪聲生成具連續(xù)性的地形;或是在藝術(shù)領(lǐng)域中使用Perlin噪聲生成圖樣。

維基百科的介紹相當(dāng)?shù)墓俜?,其實可以理解為一個隨機函數(shù),不過有以下兩個特點:

  • 連續(xù)的輸入得到的輸出更加平滑(對連續(xù)的輸入有一定權(quán)重采樣)
  • 相同的輸入必定得到相同的輸出(有的隨機函數(shù)有狀態(tài)(時間種子),這里更像是Hash函數(shù))

它適用于希望給定連續(xù)的輸入,能夠給出相對連續(xù)的隨機輸出。(例如,模擬自然地形生成:想象地形不能前一步是高山,腳下是深谷,后一步又是高山這種連續(xù)劇烈的變化)

隨機函數(shù)噪聲:

柏林噪聲:

原理

對于有經(jīng)驗的同學(xué)來說,一提到“平滑”,直覺上就會想到插值、平滑函數(shù)等。沒錯,柏林噪聲其實就是使用插值、平滑函數(shù),有時會在此基礎(chǔ)上使用倍頻,波形疊加(傅里葉變換)等方法對波形調(diào)整。

先把復(fù)雜問題簡單化,考慮一個一維的柏林噪聲生成:

上面提到了插值,插值首先要有值:靜態(tài)生成一組隨機數(shù),在一個坐標(biāo)系中每單位距離散落一個隨機數(shù)。不妨令:rands是這個隨機數(shù)數(shù)組,上圖中y1 = rands[0], y2 = rands[1], ...,x2 - x1 = delta_x = 上述的單位距離,建立一個坐標(biāo)系。

對于散落在[0, rands.Len - 1]區(qū)間的某個值n來說([rands.Len-1, rands.Len]區(qū)間對應(yīng)的x的點規(guī)定不能取到,因為下面計算會推到rands[n + 1]),假設(shè)n對應(yīng)上圖P點則有:

Noise(P) = Y1 + (Y2 - Y1) * F((xp - x1)/(delta_x))

理解下這個公式:

Y1指紅色的那個函數(shù)表達式(N),Y2指黃色的(N + 1)

Noise(P)類型插值函數(shù): Lerp = yn + (yn+1 - yn) * t, t 取值 [0, 1],在這里:

  • yn = Y1
  • yn+1 = Y2
  • t = F((xp - x1)/(delta_x))

這里的F是指平滑函數(shù),上述(t)可知F在[0,1]的輸出也必須在[0,1]區(qū)間內(nèi),通常F(x) = 6 * x^5 - 15 * x^4 - 10 * x^3,顧名思義就是對輸入進行平滑,函數(shù)圖像如下:

帶入數(shù)據(jù)來算:

Noise(p) = Y1(xp) + (Y2(xp) - Y1(xp)) * F((xp - x1)/(delta_x))

就不展開了

再來思考下它的實現(xiàn)原理:

  • 隨機:對于Noise(p)來說它的值取決于y1和y2兩個隨機數(shù)
  • 平滑: Noise(p)取值是通過前后插值得到的,其插值參數(shù)t也經(jīng)過平滑處理

其思路可以拓展到2維、3維,以2維舉例:

p落在abcd組成的2維網(wǎng)格中,其實可以視為3次1維的計算:分別計算pab、pcd所在1維直線(ab、cd)的結(jié)果,在此基礎(chǔ)上計算pad、pcd所在的線上p點的結(jié)果。這個計算會在下面的代碼實現(xiàn)中更加具象化體現(xiàn)出來。(注意有一點計算是不一樣的,一維中y = kx + b計算兩個點之間的影響在2維空間不適用,點會受到2個維度的影響,具體看下面實現(xiàn)中的示例)

經(jīng)典實現(xiàn)

static int p[512] = { 
    151,160,137,91,90,15,					
    131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,	
    190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
    88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
    77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
    102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
    135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
    5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
    223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
    129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
    251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
    49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
    138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,

    151,160,137,91,90,15,					
    131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,	
    190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
    88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
    77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
    102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
    135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
    5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
    223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
    129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
    251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
    49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
    138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};


static float3 grads[12] = {
    {1,1,0},
    {-1,1,0},
    {1,-1,0},
    {-1,-1,0},

    {1,0,1},
    {-1,0,1},
    {1,0,-1},
    {-1,0,-1},

    {0,1,1},
    {0,-1,1},
    {0,1,-1},
    {0,-1,-1}
};

float grad(int hash, float x, float y, float z)
{
    float3 v3 = float3(x,y,z);
    hash = hash & 0xb;
    return dot(grads[hash],v3);
}

int inc(int num) {
    num++;
    return num;
}

float fade(float t) {
    return t * t * t * (t * (t * 6 - 15) + 10);         
}

float perlin(float x,float y,float z)
{
    int xi = (int)x & 255;
    int yi = (int)y & 255;
    int zi = (int)z & 255;

    float xf = x - xi;
    float yf = y - yi;
    float zf = z - zi;

    float u = fade(xf);
    float v = fade(yf);
    float w = fade(zf);

    int aaa, aba, aab, abb, baa, bba, bab, bbb;
    aaa = p[p[p[    xi ]+    yi ]+    zi ];
    aba = p[p[p[    xi ]+inc(yi)]+    zi ];
    aab = p[p[p[    xi ]+    yi ]+inc(zi)];
    abb = p[p[p[    xi ]+inc(yi)]+inc(zi)];
    baa = p[p[p[inc(xi)]+    yi ]+    zi ];
    bba = p[p[p[inc(xi)]+inc(yi)]+    zi ];
    bab = p[p[p[inc(xi)]+    yi ]+inc(zi)];
    bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];

    float x1, x2, y1, y2;
    x1 = lerp(    grad (aaa, xf  , yf  , zf),           
        grad (baa, xf-1, yf  , zf),             
        u);                                     
    x2 = lerp(    grad (aba, xf  , yf-1, zf),           
    grad (bba, xf-1, yf-1, zf),             
        u);
    y1 = lerp(x1, x2, v);

    x1 = lerp(    grad (aab, xf  , yf  , zf-1),
        grad (bab, xf-1, yf  , zf-1),
        u);
    x2 = lerp(    grad (abb, xf  , yf-1, zf-1),
        grad (bbb, xf-1, yf-1, zf-1),
        u);
    y2 = lerp (x1, x2, v);

    return lerp (y1, y2, w); 
}

這段代碼是3維的perlin函數(shù),控制參數(shù)也可以實現(xiàn)1維、2維計算,從perlin函數(shù)看起:

1.靜態(tài)的p[512]數(shù)組散落隨機數(shù)數(shù)組每256個分為一塊,共兩塊(為了方便計算)。aaa = p[p[p[ xi ]+ yi ]+ zi ] 類似的其實就是進行一次哈希計算,打亂順序結(jié)果盡可能隨機,類似于一維中的每隔單位距離散落隨機數(shù)。

2.grads數(shù)組和grad函數(shù)就是確定這個p點分別受這8個頂點影響的程度,在計算上體現(xiàn)就是進行內(nèi)積(投影),注意這里的類比于一維的計算是有差別的:這里提到所謂的“梯度”,在一維計算里梯度就是指y = kx + 1中的k也就是斜率,而在三維空間中,梯度受3個維度的影響,在這里進行了簡化從預(yù)設(shè)的12個向量中選?。ㄖ劣跒槭裁匆妳⒖兼溄樱喊亓衷肼曌髡哒撐模?。

3.接著就是進行l(wèi)erp插值,對各個頂點方向上的計算結(jié)果進行平滑。

一個其他非典型實現(xiàn)示例

float rand(float2 p){
    return frac(sin(dot(p ,float2(12.9898,78.233))) * 43758.5453);
}

float noise(float2 x)
{
    float2 i = floor(x);
    float2 f = frac(x);

    float a = rand(i);
    float b = rand(i + float2(1.0, 0.0));
    float c = rand(i + float2(0.0, 1.0));
    float d = rand(i + float2(1.0, 1.0));
    float2 u = f * f * f * (f * (f * 6 - 15) + 10);

    float x1 = lerp(a,b,u.x);
    float x2 = lerp(c,d,u.x);
    return lerp(x1,x2,u.y);
}

可以看到這種實現(xiàn)和上文中的思路是一樣的,只是hash函數(shù)和計算各個方向上的影響計算進行了簡化。

波形調(diào)整

可以看出柏林函數(shù)的輸出具有“波”的特點,那么自然可以所有對于波的操作。

進行類似正弦波調(diào)幅、調(diào)頻、調(diào)相,還可以上下偏移

(f(x)=Asin(ωx+φ) + b 這里 A = 0.5, w = 2, φ = 1, b = 0.5)

波的疊加

傅里葉變換說一個波可以由為n個波疊加而成,疊加結(jié)果如圖所示。

波形的調(diào)整在實際應(yīng)用中作用很大,如:

  • 模擬生成地圖中某個區(qū)域的地質(zhì)運動劇烈,地形起伏很大,可以對波形調(diào)幅把振幅調(diào)大。
  • 如果想讓生成的波形更加連續(xù),可以先調(diào)頻(倍頻)然后疊加

以上就是基于C++實現(xiàn)柏林噪聲算法(Perlin Noise)的詳細內(nèi)容,更多關(guān)于C++柏林噪聲算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++結(jié)構(gòu)體字節(jié)對齊和共用體大小

    C++結(jié)構(gòu)體字節(jié)對齊和共用體大小

    這篇文章主要介紹了C++結(jié)構(gòu)體字節(jié)對齊和共用體大小,結(jié)構(gòu)體內(nèi)存對齊在筆試和面試中經(jīng)常被問到,所以這篇文章做個總結(jié),首先通過代碼驗證不同結(jié)構(gòu)體的內(nèi)存大小,需要的朋友可以參考下
    2021-11-11
  • C++類型轉(zhuǎn)換和IO流操作處理教程

    C++類型轉(zhuǎn)換和IO流操作處理教程

    這篇文章主要給大家介紹了關(guān)于C++類型轉(zhuǎn)換和IO流操作處理的相關(guān)資料,標(biāo)準(zhǔn)C++為了加強類型轉(zhuǎn)換的可視性,引入了四種命名的強制類型轉(zhuǎn)換操作符,文中給出了詳細的代碼示例,需要的朋友可以參考下
    2023-08-08
  • C++輸入輸出操作符重載的深入分析

    C++輸入輸出操作符重載的深入分析

    本篇文章是對C++輸入輸出操作符重載進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++11新特性之變長參數(shù)模板詳解

    C++11新特性之變長參數(shù)模板詳解

    本文主要介紹了C++11變長參數(shù)模板,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • C語言動態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解

    C語言動態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解

    但是在實際的編程中,往往會發(fā)生這種情況,即所需的內(nèi)存空間取決于實際輸入的數(shù)據(jù),而無法預(yù)先確定 。為了解決上述問題,C語言提供了一些內(nèi)存管理函數(shù),這些內(nèi)存管理函數(shù)可以按需要動態(tài)的分配內(nèi)存空間,也可把不再使用的空間回收再次利用
    2022-12-12
  • C利用語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)之隊列

    C利用語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)之隊列

    隊列 (Queue):簡稱隊,是另一種限定性的線性表,它只允許在表的一端插入元素,而在另一端刪除元素。q=(a1, a2, a3, … an),其中a1為隊頭,an為隊尾,下面文章小編將為大家詳細介紹,需要的下伙伴可以參考一下
    2021-10-10
  • C++ stringstream格式化輸出輸入詳情

    C++ stringstream格式化輸出輸入詳情

    這篇文章主要介紹了C++ stringstream格式化輸出輸入,首先string str; cin>>str;遇到空格結(jié)束;于是乎產(chǎn)生了getline(),可與得到一行字符串;空格自動去掉,下面來看看文章的詳細內(nèi)容,需要的小伙伴可以參考一下
    2021-11-11
  • C++中實現(xiàn)把表的數(shù)據(jù)導(dǎo)出到EXCEL并打印實例代碼

    C++中實現(xiàn)把表的數(shù)據(jù)導(dǎo)出到EXCEL并打印實例代碼

    這篇文章主要介紹了實現(xiàn)把表的數(shù)據(jù)導(dǎo)出到EXCEL并打印實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • C++ LeetCode1780判斷數(shù)字是否可以表示成三的冪的和

    C++ LeetCode1780判斷數(shù)字是否可以表示成三的冪的和

    這篇文章主要為大家介紹了C++ LeetCode1780判斷數(shù)字是否可以表示成三的冪的和題解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • C++??STL?_?Vector使用及模擬實現(xiàn)

    C++??STL?_?Vector使用及模擬實現(xiàn)

    這篇文章主要介紹了C++ STL_Vector使用及模擬實現(xiàn),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08

最新評論

道孚县| 揭西县| 延寿县| 临潭县| 云霄县| 南涧| 遵义县| 红安县| 泰安市| 绥德县| 彭山县| 安溪县| 中江县| 凤城市| 湘潭县| 庆云县| 定安县| 海林市| 开江县| 开远市| 务川| 犍为县| 永川市| 南川市| 连平县| 屯留县| 台南市| 屯门区| 林周县| 孝感市| 云南省| 大埔县| 丰宁| 临江市| 蒙城县| 中牟县| 隆尧县| 华坪县| 辰溪县| 忻州市| 越西县|