在计算机图形学中,Perlin Noise 是一种广泛使用的算法,用于生成自然的、随机但平滑的纹理和效果。它最初由 Ken Perlin 在 1983 年提出,并因其卓越的效果而被应用于电影、游戏和其他视觉艺术领域。本文将通过一个简单的着色器代码示例,向您介绍如何在 Shadertoy 中实现 Perlin Noise,并探讨其背后的原理。
1. Perlin Noise 的基本概念
Perlin Noise 是一种梯度噪声(Gradient Noise),其核心思想是通过定义一组随机梯度向量,并在这些梯度向量之间进行插值,从而生成连续且平滑的噪声图案。与传统的值噪声(Value Noise)相比,Perlin Noise 更加高效且具有更高的视觉质量。
以下是 Perlin Noise 的主要步骤:
- 网格划分:将空间划分为规则的网格。
- 随机梯度:为每个网格点分配一个随机梯度向量。
- 距离计算:计算输入点到最近网格点的距离。
- 插值:使用光滑插值函数(如三次多项式)对多个网格点的影响进行混合。
2. 着色器代码解析
以下是我们提供的 Perlin Noise 着色器代码:
// 生成随机梯度向量
vec2 random2(vec2 pos){
vec2 fractPos = vec2(dot(pos, vec2(432., 235.)), dot(pos, vec2(232., 735.)));
return 2.*fract(sin(fractPos) * 1000.) - 1.;
}
// Gradient Noise 函数
float noise(vec2 st) {
vec2 i = floor(st); // 获取当前点所在的网格坐标
vec2 f = fract(st); // 获取当前点在网格中的相对位置
vec2 u = f*f*(3.0-2.0*f); // 使用光滑插值函数
// 对四个相邻网格点的梯度进行插值
return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( random2(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 st = gl_FragCoord.xy/u_resolution.xy; // 归一化屏幕坐标
st.x *= iResolution.x/iResolution.y; // 校正宽高比
vec3 color = vec3(0.0);
vec2 pos = vec2(st*10.0); // 缩放坐标以放大噪声细节
color = vec3( noise(pos)*.5+.5 ); // 将噪声值映射到颜色范围 [0,1]
fragColor = vec4(color,1.0); // 输出最终颜色
}
代码详解
1. random2
函数
该函数用于生成随机梯度向量。我们通过以下步骤实现:
- 利用
dot
和sin
函数生成伪随机数。 - 将结果归一化到 [-1, 1] 范围内。
2. noise
函数
这是 Perlin Noise 的核心部分:
- 网格划分:通过
floor
和fract
函数,将输入点划分为整数网格坐标i
和小数部分f
。 - 光滑插值:使用
f*f*(3.0-2.0*f)
计算平滑插值因子u
。 - 梯度插值:通过对四个相邻网格点的梯度向量进行双线性插值,生成最终的噪声值。这里要注意的一点是如
f - vec2(0.0,1.0)
,需要理解为两个向量相减的结果
如A-B=C,为向量B的末端指向向量A的末端所形成的结果向量C
3. 主函数 main
- 首先,我们将屏幕坐标归一化并校正宽高比。
- 然后,通过缩放坐标来控制噪声的细节级别。
- 最后,将噪声值映射到颜色范围,并输出到屏幕。
3. 运行效果
运行上述代码后,您将看到一个平滑的噪声图案。这种图案可以用于模拟云层、地形、水波等多种自然现象。通过调整缩放因子(例如 st*10.0
),您可以改变噪声的频率和细节级别。
4. 应用场景
Perlin Noise 的应用非常广泛,包括但不限于以下领域:
- 地形生成:模拟山脉、丘陵等地形特征。
- 纹理合成:生成逼真的材质纹理,如木材、金属等。
- 粒子系统:为粒子运动添加自然的随机性。
- 动画效果:生成动态的背景或过渡效果。
5. 总结
Perlin Noise 是一种强大且灵活的工具,能够帮助开发者和艺术家生成各种复杂的自然效果。通过本文的介绍,您已经了解了 Perlin Noise 的基本原理,并掌握了如何在 Shadertoy 中实现它。希望这篇文章能激发您的创造力,探索更多有趣的着色器实验!
如果您想进一步学习,可以尝试以下扩展方向:
- 实现多层噪声叠加(Fractal Brownian Motion, FBM)。
- 添加时间维度,生成动态噪声效果。
- 结合其他算法(如 Voronoi Noise)生成更复杂的效果。