WebGL进阶——走进图形噪声
Posted 前端外刊评论
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL进阶——走进图形噪声相关的知识,希望对你有一定的参考价值。
导语:大自然蕴含着各式各样的纹理,小到细胞菌落分布,大到宇宙星球表面。运用图形噪声,我们可以在3d场景中模拟它们,本文就带大家一起走进万能的图形噪声。
概述
图形噪声,是计算机图形学中一类随机算法,经常用来模拟自然界中的各种纹理材质,如下图的云、山脉等,都是通过噪声算法模拟出来的。
通过不同的噪声算法,作用在物体纹理和材质细节,我们可以模拟不同类型的材质。
基础噪声算法
一个基础的噪声函数的入参通常是一个点坐标(这个点坐标可以是二维的、三维的,甚至N维),返回值是一个浮点数值: noise(vec2(x,y))
。 我们将这个浮点值转成灰度颜色,形成噪声图,具体可以通过编写片元着色器程序来绘制。
上图是各类噪声函数在片元着色器中的运行效果,代码如下:
// noise fragment shader
varying vec2 uv;
float noise(vec2 p) {
// TODO
}
void main() {
float n = noise(uv); // 通过噪声函数计算片元坐标对应噪声值
gl_FragColor = vec4(n, n, n, 1.0);
}
其中 noise(st)
的入参 st
是片元坐标,返回的噪声值映射在片元的颜色上。 目前基础噪声算法比较主流的有两类:1. 梯度噪声;2. 细胞噪声;
梯度噪声 (Gradient Noise)
梯度噪声产生的纹理具有连续性,所以经常用来模拟山脉、云朵等具有连续性的物质,该类噪声的典型代表是Perlin Noise。
其它梯度噪声还有Simplex Noise和Wavelet Noise,它们也是由Perlin Noise演变而来。
算法步骤
梯度噪声是通过多个随机梯度相互影响计算得到,通过梯度向量的方向与片元的位置计算噪声值。这里以2d举例,主要分为四步:1. 网格生成;2. 网格随机梯度生成;3. 梯度贡献值计算;4. 平滑插值
第一步,我们将2d平面分成m×n个大小相同的网格,具体数值取决于我们需要生成的纹理密度(下面以4×4作为例子);
#define SCALE 4. // 将平面分为 4 × 4 个正方形网格
float noise(vec2 p) {
p *= SCALE;
// TODO
}
第二步,梯度向量生成,这一步是根据第一步生成的网格的顶点来产生随机向量,四个顶点就有四个梯度向量;
我们需要将每个网格对应的随机向量记录下来,确保不同片元在相同网格中获取的随机向量是一致的。
// 输入网格顶点位置,输出随机向量
vec2 random(vec2 p){
return -1.0 + 2.0 * fract(
sin(
vec2(
dot(p, vec2(127.1,311.7)),
dot(p, vec2(269.5,183.3))
)
) * 43758.5453
);
}
如上,借用三角函数sin(θ)的来生成随机值,入参是网格顶点的坐标,返回值是随机向量。
第三步,梯度贡献计算,这一步是通过计算四个梯度向量对当前片元点P的影响,主要先求出点P到四个顶点的距离向量,然后和对应的梯度向量进行点积。
如图,网格内的片元点P的四个顶点距离向量为a1, a2, a3, a4,此时将距离向量与梯度向量g1, g2, g3, g4进行点积运算:c[i] = a[i] · g[i];
以上是关于WebGL进阶——走进图形噪声的主要内容,如果未能解决你的问题,请参考以下文章