perlin噪聲

手賤去點了圖形學裏面的噪聲課程,而後一個週末就交代在這上面了,仍是有些雲裏霧裏。html

噪聲就是給定一個輸入變量,生成一個值在0~1範圍內的僞隨機變量的函數。在圖形學中通常是輸入一個座標獲得一個範圍在0~1之間的變量,在利用各類顏色計算獲得一些比較酷炫的效果,像火焰、雲彩、地形等。下面就是perlin噪聲生成個灰度圖。算法

 沒啥意思是吧,那麼看下面這個:函數

如今說說最有名的噪聲算法:perlin噪聲又稱柏林噪聲,噪聲鼻祖。柏林噪聲是基於網格的,假想了一堆格網,每一個格子由四個頂點組成(三維場景就是立方體,每一個立方體由8個頂點組成);post


圖1:小藍點表明輸入值在單元正方形裏的空間座標,其餘4個點則是單元正方形的各頂點ui

每一個頂點有一個僞隨機向量(就是一個向量,由一個僞隨機函數生成的,僞隨機函數能夠隨便找一個,perlin老爺子也是隨便找了一個)。this


圖2:各頂點上的梯度向量隨機選取結果url

 同時這四個頂點距離落在格網中的點,能夠獲得四個距離向量。spa


圖3:各個距離向量.net

將圖2獲得的梯度向量與圖3的距離向量作點乘,因爲都是單位向量點乘積在0-1之間。同時這個點最終的值由四個點乘積根據權重關係作差值獲得。code

這個差值函數使用緩和曲線(ease curves)來計算它們的權重和。在原始的Perlin噪聲實現中,緩和曲線是s(t)=3t2−2t3s(t)=3t2−2t3,在2002年的論文6中,Perlin改進爲s(t)=6t5−15t4+10t3s(t)=6t5−15t4+10t3。(原文來自這篇文章

 

好了如今來看看第一個效果是怎麼作出來的(至於第二個麼,咳咳,等我徹底看明白會寫出來的)

這個效果是來自ShaderToy中的。

// 生成一個僞隨機向量,這個函數是找的一個僞隨機函數,能夠用其餘的僞隨機函數代替
vec2 hash( vec2 x )  // replace this by something better
{
    const vec2 k = vec2( 0.3183099, 0.3678794 );
    x = x*k + k.yx;
    // fract的做用是取小數,那麼小數在0~1之間;乘以2再加-1,最終返回座標範圍在-1~1之間
    return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );
}

float noise( in vec2 p )
{
    vec2 i = floor( p ); // 取一個格子
    vec2 f = fract( p ); // 獲取在格子內的位置
    
    vec2 u = f*f*(3.0-2.0*f); // 根據權重的平滑函數

    return mix( 
               mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ), 
                     dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ),
                     u.x), // 將水平方向獲得的兩個點乘積根據水平方向的權重作差值
                mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ), 
                     dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ),
                     u.x), 
          u.y);// 在豎直方向上對兩個值按權重進行差值
}

// -----------------------------------------------

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 p = fragCoord.xy / iResolution.xy; // 像素位置除以分辨率,座標範圍在0~1之間

    vec2 uv = p*vec2(iResolution.x/iResolution.y,1.0); // 這時u.x範圍在0~寬高比之間,u.y在0~1之間
    
    float f = 0.0;
    
    // left: noise    
    if( p.x<0.6 )// 左邊部分簡單的生成單噪聲
    {
        f = noise( 32.0*uv ); // 32做爲一個參數音箱噪音頻率
    }
    // right: fractal noise (4 octaves)
    else    // 右邊部分使用四個倍頻在模擬效果
    {
        uv *= 8.0;
        mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
        f  = 0.5000*noise( uv ); uv = m*uv;
        f += 0.2500*noise( uv ); uv = m*uv;
        f += 0.1250*noise( uv ); uv = m*uv;
        f += 0.0625*noise( uv ); uv = m*uv;
    }

    f = 0.5 + 0.5*f;
    
    f *= smoothstep( 0.0, 0.005, abs(p.x-0.6) );    // 生成中間那條黑線,smoothstep的做用看這裏,https://blog.csdn.net/libing_zeng/article/details/68924521


 

    fragColor = vec4( f * iTime, f, f, 1.0 );
}

 

 最後仍是列一下大神們的文章:

【圖形學】談談噪聲

一篇文章搞懂柏林噪聲算法,附代碼講解

[數學][轉載][柏林噪聲]

相關文章
相關標籤/搜索