WebGL进阶——走进图形噪声

Posted 前端外刊评论

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL进阶——走进图形噪声相关的知识,希望对你有一定的参考价值。

导语:大自然蕴含着各式各样的纹理,小到细胞菌落分布,大到宇宙星球表面。运用图形噪声,我们可以在3d场景中模拟它们,本文就带大家一起走进万能的图形噪声。

概述

图形噪声,是计算机图形学中一类随机算法,经常用来模拟自然界中的各种纹理材质,如下图的云、山脉等,都是通过噪声算法模拟出来的。

通过不同的噪声算法,作用在物体纹理和材质细节,我们可以模拟不同类型的材质。

WebGL进阶——走进图形噪声

基础噪声算法

一个基础的噪声函数的入参通常是一个点坐标(这个点坐标可以是二维的、三维的,甚至N维),返回值是一个浮点数值: noise(vec2(x,y))。 我们将这个浮点值转成灰度颜色,形成噪声图,具体可以通过编写片元着色器程序来绘制。

WebGL进阶——走进图形噪声

上图是各类噪声函数在片元着色器中的运行效果,代码如下:

 
   
   
 
  1. // noise fragment shader

  2. varying vec2 uv;

  3. float noise(vec2 p) {

  4. // TODO

  5. }

  6. void main() {

  7. float n = noise(uv); // 通过噪声函数计算片元坐标对应噪声值

  8. gl_FragColor = vec4(n, n, n, 1.0);

  9. }

其中 noise(st)的入参 st是片元坐标,返回的噪声值映射在片元的颜色上。 目前基础噪声算法比较主流的有两类:1. 梯度噪声;2. 细胞噪声;

梯度噪声 (Gradient Noise)

梯度噪声产生的纹理具有连续性,所以经常用来模拟山脉、云朵等具有连续性的物质,该类噪声的典型代表是Perlin Noise。

WebGL进阶——走进图形噪声

其它梯度噪声还有Simplex Noise和Wavelet Noise,它们也是由Perlin Noise演变而来。

算法步骤

梯度噪声是通过多个随机梯度相互影响计算得到,通过梯度向量的方向与片元的位置计算噪声值。这里以2d举例,主要分为四步:1. 网格生成;2. 网格随机梯度生成;3. 梯度贡献值计算;4. 平滑插值

WebGL进阶——走进图形噪声

第一步,我们将2d平面分成m×n个大小相同的网格,具体数值取决于我们需要生成的纹理密度(下面以4×4作为例子);

 
   
   
 
  1. #define SCALE 4. // 将平面分为 4 × 4 个正方形网格

  2. float noise(vec2 p) {

  3. p *= SCALE;

  4. // TODO

  5. }

第二步,梯度向量生成,这一步是根据第一步生成的网格的顶点来产生随机向量,四个顶点就有四个梯度向量;

WebGL进阶——走进图形噪声

我们需要将每个网格对应的随机向量记录下来,确保不同片元在相同网格中获取的随机向量是一致的。

 
   
   
 
  1. // 输入网格顶点位置,输出随机向量

  2. vec2 random(vec2 p){

  3. return -1.0 + 2.0 * fract(

  4. sin(

  5. vec2(

  6. dot(p, vec2(127.1,311.7)),

  7. dot(p, vec2(269.5,183.3))

  8. )

  9. ) * 43758.5453

  10. );

  11. }

如上,借用三角函数sin(θ)的来生成随机值,入参是网格顶点的坐标,返回值是随机向量。

第三步,梯度贡献计算,这一步是通过计算四个梯度向量对当前片元点P的影响,主要先求出点P到四个顶点的距离向量,然后和对应的梯度向量进行点积。

WebGL进阶——走进图形噪声

如图,网格内的片元点P的四个顶点距离向量为a1, a2, a3, a4,此时将距离向量与梯度向量g1, g2, g3, g4进行点积运算:c[i] = a[i] · g[i];