【技术美术】程序化噪波实现

本文最后更新于 2024年11月19日 晚上

【技术美术】程序化噪波实现

噪波基本原理

首先通过观察噪波,可以确定我们的需求:

  • 噪波的特性
    • 随机性:宏观来看,各区域的颜色是随机的。
    • 平滑性:微观来看,各像素间的颜色是连续的。
    • 稳定性:同样的输入参数只会得到同样的结果。

而为了实现这些特性,需要采样以下方法:

  • 噪波的实现
    1. 随机性:利用随机数生成算法获取随机值。
    2. 稳定性:随机数算法实际是一种哈希函数,产生的是可控的伪随机。
    3. 平滑性:通过平滑算法平滑随机值,使各区域间有颜色过渡。

而这些方法的具体实现,根据计算方式的不同,引出了不同的噪波类型:

  • 噪波的种类
    • 基于晶格
      • 值噪波(根据值线性插值):
        • Value 噪波
      • 梯度噪波(根据向量点乘插值)
        • Perlin 噪波(柏林噪波):最早最流行的噪波实现。
        • Simplex 噪波(单纯形噪波):相比柏林噪波,开销更低且减弱方向伪影。
        • Simulation 噪波
        • Wavelet 噪波
    • 基于点
      • Worley 噪波(细胞格噪波)

实现随机数生成

随机数生成算法都是伪随机,伪随机是通过一个固定的数学公式算出来的,理论上可以预测,所以叫伪随机。之所以能形成随机效果是因为算法过于复杂,变化过于跳跃,难以简单预测出结果。

广义的随机数算法依赖迭代实现,但在 Shader 中很难做到,且不能满足稳定性要求,所以 shader 中的随机数生成算法需另辟蹊径。

最常用的实现方式如下:

rand(x)=fract(sin(x)a)rand(x) = fract(sin(x) * a)

  • a:一个非常大的常数。

其原理就是通过系数 aa 大幅增加函数的变化率,使 x 即使发生一丁点变化,其结果也会千差万别,从而看上去随机了。

实现多维随机数

rand(x)=fract(sin(xb)a)rand(\vec{x}) = fract(sin(\vec{x} \cdot \vec{b}) * a)

  • a:与一维中的含义一样。
  • b:一个任意给定的向量。

多维随机数生成与一维随机数生成本质是一样的,只是要先用 dot()dot() 将多维合并成一维而已。

实现随机数平滑

参考资料


【技术美术】程序化噪波实现
https://bdffzi-blog.pages.dev/posts/596080998.html
作者
BDFFZI
发布于
2024年11月19日
许可协议