欢迎继续一起踏上 The Journey of Chaos, 关于 Shader 生成技术的一些基础性学习。噪声会分为以下几篇内容学习
-
柏林噪声 Gradient Noise(本篇)
-
二维柏林噪声 Gradient Noise
-
三维柏林噪声与计算优化 Simplex Noise
-
Voronoi噪声 Cell Noise
-
FBM深入
本篇主要是理解 柏林噪声的具体实现原理,相关的学习资料和衍生内容在文尾。
Perlin 噪声
为什么柏林噪声相对于值噪声表现更好。 个人感觉有点类似于之前学过的 Iphone的 G2连续 。 一个曲线或曲面可以被描述为具有 Gn 连续性,n 是表示光滑度的增量,即在曲线上取一点,然后分析该点与其两侧线段的关系。
-
G0: 两侧曲线在这一点相遇(位置连续)。
-
G1: 两侧曲线这一点的切线方向相同(相切连续)。
-
G2: 两侧曲线在这一点的曲率相同(曲率连续)。
Gradient Noise就是 G2, Value Noise就是 G1...... 当然大概率是我学串了...
回到我们的主题 柏林噪声, 它是由Ken Perlin在20世纪80年代发明的一种伪随机梯度噪声。主要用于生成自然的纹理效果,如云彩、火焰、海浪等,因为生成的噪声具有连续的梯度变化,显得更加平滑和自然。柏林噪声通过插值方法计算,输入可以是多维的,如一维、二维、三维等,从而生成不同维度下的噪声。
本章会接触到一个叫做梯度 Gradinent的数学概念,不过不要害怕,对于柏林噪声来说他只是一个值而已。 先记住一个概念,梯度就是值变化最快的方向。 例如在一维的柏林噪声中,一维梯度就是曲线的导数, 二维的梯度可以想象我们在一个山坡上,我们朝那个方向迈出步子,让我们所在位置高度变化最快,这个方向就是二维的梯度。 在高维的梯度就纯粹是抽象的向量与偏导数概念。
为了更好的了解,我们从一维柏林开始
一维 Perlin函数
2501265738
考虑上面 A,B,C三个点,我们为每个点选择一个斜线。还记得高中里面这条线是该点的斜率。 所以三条线的公式应该有
这里的 n0, n1, n2
就是斜率,也是导数值,👀 一维的导数就是梯度值。
这个时候我们再利用上一节课讲到的插值函数Interpolate和平滑函数 Ease. 插值我们依然选择线性插值
缓和函数我们依然选择 Smoothstep
套用到上面公式中,可得
这个函数的曲线就是如下蓝色所示。 That's All 这就是一维的 Perlin噪声。 和我们之前 G2连续好像...
2501263633
一维Perlin代码
理解起数学公式之后,写代码就是一个很简单的事情。 首先实现我们的插值函数
float linearInterpolate(float a , float b,float x) { return a + (b -a ) * x;}
在实现 ease函数
float ease(float x) { return x * x * (3.0 - 2.0 * x);}
套用公式实现就是先 perlin噪声
float perlinNoise(float x) { float i = floor(x); float f = fract(x); float d0 = hash11(i+0.0); float d1 = hash11(i+1.0); return linearInterpolate(d0, d1, ease(f));}
这个时候我们在将 perlinNoise产生的值作为 y值,画一个线,就可以看到一个噪声曲线啦
float y = 0.5 + 0.5 * perlinNoise(uv.x); vec3 col = vec3(1.0 - smoothstep( 0.0, 0.01, abs(p.y-y) ));
2501262448
其实拿到上面那根线进行简单的加工就可以很有意思。。。 比如重复几条线,然后给线加点颜色
const float lineNum = 8.; for (float i =0.; i< lineNum; i++) { float rand = perlinNoise(uv.x * 1.2 * i / lineNum + iTime) * 0.5 + 0.25; float halfWidth = mix(0.015, 0.15, rand * horizontalFade) / 2.0; col += smoothstep( halfWidth/3., 0.0, abs(p.y-rand) ) * palette(rand * 3.0); col += smoothstep(halfWidth/10. + 0.015,halfWidth/10., abs(p.y-rand) )* palette(rand * 3. + 23.) * 0.2; }
可以得到下面很有意思的图像
资料
-
How to turn a few Numbers into Worlds (Fractal Perlin Noise) www.youtube.com/watch?v=ZsE…
-
Simondev noise youtu.be/sChQCdbLdHE…
-
柏林老哥代码 1980S mrl.cs.nyu.edu/~perlin/doc…