利用柏林噪声生成噪声函数
噪音函数的生成原理就不多说了,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);
即可生成一张丑陋的草地纹理