分形布朗运动
在「噪声的艺术(一)」中我们学习了 Value Noise, Gradient Noise 以及 Simplex Noise 这三种创建噪声的方法。随后我们又在「噪声的艺术(二)」中学到了基于网格的生成方法。是时候将这些技法融入真正的艺术效果中了。
以下内容来自「the book of shaders」分形布朗运动一章。
线性波
正弦波拥有频率和振幅两个特征值,收音机上的 AM(调幅)和 FM(调频)更改的就是这两个特征值。
float amplitude = 1.;
float frequency = 1.;
y = amplitude * sin(x * frequency);
大学里学过的傅立叶变换让我们知道波是可以叠加的。
从音乐理论上说,每个音符都和一个特定的频率相关联。这些音符和频率的关系遵从一定的模式,也就是我们所说的音阶,一个八度(octave)对应着频率上的加倍或减半。
叠加噪声
还记得在「噪声的艺术(一)」中我们学到的 Perlin 噪声的模拟过程吗?既然波是可以叠加的,噪声也可以。
通过在循环(循环次数为 octaves,一次循环为一个八度)中叠加噪声,并以一定的倍数(lacunarity,间隙度)连续升高频率,同时以一定的比例(gain,增益)降低 噪声 的振幅,最终的结果会有更好的细节。这项技术叫“分形布朗运动(fractal Brownian Motion)”(fBM),或者“分形噪声(fractal noise)”
比如下面的例子中,我们叠加了 6 个八度:
const int octaves = 6;
float lacunarity = 2.0;
float gain = 0.5;
float amplitude = 0.5;
float frequency = 1.;
for (int i = 0; i < octaves; i++) {
y += amplitude * noise(frequency*x);
frequency *= lacunarity;
amplitude *= gain;
}
效果如下,可见初始 Perlin 噪声的特征已经被隐藏了:
值得注意的是,虽然 Perlin 噪声计算量不如使用网格生成方式的算法例如 Voronoi,看似效果较差,但是经过 fbm,其实效果已经很好了。
注意,随着我们一个八度接一个八度地往上叠加,曲线看起来有越来越多的细节,同时,自相似性也越来越明显。如果你放大看看,曲线的局部和整体看起来很相似,并且,任选两段不同的部分看起来也多少有些相似。这是一个数学上的分形的重要性质,我们在上面的循环中模拟了这个性质。
模拟自然界效果
这项技术被广泛地应用于构造程序化风景。fBm 的自相似性能够很完美地模拟山脉,因为山脉形成过程中的腐蚀形成了这种不同尺度上的自相似性。
山脊
IQ 大神的作品,希望自己有一天能完全弄懂生成的原理。
完全通过下面的 texture 生成,包含了光照,阴影,摄像机运动等等。
流动的气体
又是 IQ 大神带来的一种华丽效果,他称之为 domain warping。 大致思想是递归调用 fbm:
f(p) = fbm( p + fbm( p + fbm( p ) ) )
比如选取一些特殊的参数,再加上 u_time
带上运动效果:
vec2 q = vec2(0.);
q.x = fbm( st + 0.00*u_time);
q.y = fbm( st + vec2(1.0));
vec2 r = vec2(0.);
r.x = fbm( st + 1.0*q + vec2(1.7,9.2)+ 0.15*u_time );
r.y = fbm( st + 1.0*q + vec2(8.3,2.8)+ 0.126*u_time);
float f = fbm(st+r);
最终可以实现类似雾气的流动效果:
总结
「the book of shaders」也只更新到这一章,希望后续章节能够继续更新吧。