利用柏林噪声生成噪声函数

Posted 风轻云淡走天涯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用柏林噪声生成噪声函数相关的知识,希望对你有一定的参考价值。

噪音函数的生成原理就不多说了,https://zh.wikipedia.org/wiki/Perlin%E5%99%AA%E5%A3%B0 可以参考维基百科

 

如右图所示,给正方形四个顶点分配四个随机单位向量,正方形内的像素可以利用这四个向量进行插值。

对指向正方形内像素的向量和顶点的随机向量分别进行点积,可以得到四个标量,利用这四个标量插值得到像素的值。

 

void noiseTexture::make_noise(float noise[][128][4])
{
    
    Vector2f<GLfloat> randomTable[128]; //生成方向表
    
    int H[128];                        //将方向表顺序打乱
    
    const float delta = pi2 / 128;     //用于生成128个方向的单位向量
    
    for (int i = 0; i < 128; i++)
    {
        float theta = delta*static_cast<float>(i);

        randomTable[i] = Vector2f<GLfloat>(sinf(theta), cosf(theta));
    }
    
    //初始化H
    for (int i = 0; i < 128; i++)
        H[i] = i;
    
    //打乱H的顺序
    for (int i = 0; i < 128; i++)
    {
        int j = rand() % 128;
        std::swap(H[i], H[j]);
    }

    //32代表在一个正方形内进行32*32将插值,共有128/32 * 128/32 = 16个正方形
    //He代表插值得到的振辐
    float p = 1.0/32,f; float He = 1.f;
    
    int k = 0;
    while (k<4)
    {
        //遍历表格的每一个点
        for (int i = 0; i < 128; i++)
        {
            for (int j = 0; j < 128; j++)
            {
                float now_x = p*i;            
                float now_y = p*j;

                Vector2f<GLfloat> now_xy(p*i, p*j);      //当前位置

                Vector2f<GLfloat> intxy((float)static_cast<int>(now_x), (float)static_cast<int>(now_y));//正方形左上角位置

                Vector2f<GLfloat> weight_xy = now_xy - intxy; //当前位置相对左上角的位置
                
                GLfloat delta_x = weight_xy.data[0] * weight_xy.data[0] * (3.f - 2.*weight_xy.data[0]); //函数f(k)
                
                GLfloat delta_y = weight_xy.data[1] * weight_xy.data[1] * (3.f - 2.*weight_xy.data[1]); //函数f(k)

                //HH(static_cast<int>(now_x), static_cast<int>(now_y))散列到H的一个位置,可以自行定义
                //randomTable[H[HH(static_cast<int>(now_x), static_cast<int>(now_y))]] *(weight_xy - Vector2f<GLfloat>(.0f, .0f))为计算标量值
                //mix为插值函数
                float k1 = mix(randomTable[H[HH(static_cast<int>(now_x), static_cast<int>(now_y))]] *
                    (weight_xy - Vector2f<GLfloat>(.0f, .0f)),
                    randomTable[H[HH(static_cast<int>(now_x) + 1, static_cast<int>(now_y))]] *
                    (weight_xy - Vector2f<GLfloat>(1.0f, .0f)), delta_x);


                float k2 = mix(randomTable[H[HH(static_cast<int>(now_x), static_cast<int>(now_y)+1)]] *
                    (weight_xy - Vector2f<GLfloat>(.0f, 1.0f)),
                    randomTable[H[HH(static_cast<int>(now_x) + 1, static_cast<int>(now_y)+1)]] *
                    (weight_xy - Vector2f<GLfloat>(1.0f, 1.0f)), delta_x);

                float o = mix(k1, k2, delta_y);

                noise[i][j][k]= o*He;
            }
        }
        p = p * 2;   //减少正方形的大小
        He = He*0.75f;//减小振幅
        k++;
    }
}

以上为噪声纹理的生成代码

在像素着色器中如下的简单使用

          vec4 noise = texture2D(gSampler, fract(TexCoord0.st*1));
          return vec4(0.,(noise.x+noise.y+noise.z+noise.w)*0.5+0.6,0,1);

即可生成一张丑陋的草地纹理

 

以上是关于利用柏林噪声生成噪声函数的主要内容,如果未能解决你的问题,请参考以下文章

柏林噪声的每顶点法线?

需要分数布朗噪声(FBM)与柏林噪声澄清

运动的柏林噪音?

MATLAB | MATLAB地形生成:矩形迭代法 · 傅里叶逆变换法 · 分形柏林噪声法

MATLAB | MATLAB地形生成:矩形迭代法 · 傅里叶逆变换法 · 分形柏林噪声法

Ray Tracing The Next Week 超详解 光线追踪2-4