Simplex Noise
Perlin Noise的复杂度是O(2^n),随维数上升计算量会显著增长。2001年Perlin又提出了优化到O(n^2)simplex noise。
Simplex噪声也是一种基于晶格的梯度噪声,它和Perlin噪声在实现上唯一不同的地方在于,它的晶格并不是方形(在2D下是正方形,在3D下是立方体,在更高纬度上我们称它们为超立方体,hypercube),而是单形(simplex)。在n维空间下,超立方体的顶点数目是2𝑛,而单形的顶点数目是𝑛+1,这使得我们在计算梯度噪声时可以大大减少需要计算的顶点权重数目。
下一个问题就是,我们应当如何找到像素点所处的单形呢?
我们可以把单形进行坐标偏斜(skewing),把平铺空间的单形变成一个新的网格结构,这个网格结构是由超立方体组成的,而每个超立方体又由一定数量的单形构成。
详细代码如下,解读见乐乐老师的文章:
float simplex_noise(vec2 p)
{
const float K1 = 0.366025404; // (sqrt(3)-1)/2;
const float K2 = 0.211324865; // (3-sqrt(3))/6;
vec2 i = floor(p + (p.x + p.y) * K1);
vec2 a = p - (i - (i.x + i.y) * K2);
vec2 o = (a.x < a.y) ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
vec2 b = a - (o - K2);
vec2 c = a - (1.0 - 2.0 * K2);
vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);
vec3 n = h * h * h * h * vec3(dot(a, hash22(i)), dot(b, hash22(i + o)), dot(c, hash22(i + 1.0)));
return dot(vec3(70.0, 70.0, 70.0), n);
}
Worley Noise
Celluar Noise生成的噪声图由很多个“晶胞”组成,每个晶胞向外扩张,晶胞之间相互抑制。这类噪声可以模拟细胞形态、皮革纹理等。1996年,Steven Worley发表的论文《A Cellular Texture Basis Function》提出了一种用于实现cellular texture方法,能有有限的资源时间内快速生成Cell噪声,因此Cellular噪声也常被称为Worley噪声。
该算法基于沃罗诺伊(Voronio)的空间分割理论,在空间中,我们随机放置若干特征点(Feature points),对任一输入点P,计算其到所有特征点的距离,这个距离值的最小值就是最后的噪声值。但是计算输入点到所有点到距离最小值会花费大量的时间,因此worley提出了基于晶格的优化算法,每个输入点只需计算自己所处的晶格和周边8个晶格中的特征点距离即可。
vec2 Hash(vec2 P)
{
return fract(cos(P*mat2(-64.2,71.3,81.4,-29.8))*8321.3);
}
float Worley(vec2 P)
{
float Dist = 1.;
vec2 I = floor(P);
vec2 F = fract(P);
for(int X = -1;X<=1;X++)
for(int Y = -1;Y<=1;Y++)
{
float D = distance(Hash(I+vec2(X,Y))+vec2(X,Y),F);
Dist = min(Dist,D);
}
return Dist;
}
Worley Noise的返回值是一个距离场,如果希望获得Voronoi图,只需将dist替换为vec2保存最近点的位置信息即可。
Seamless Noise
上一篇谈到,生成噪声动画需要n+1维的噪声。而如果生成可无缝拼接的噪声,需要2*n维的噪声。
目前公认比较好的一种方法,就是在2n维上计算n维可平铺噪声。我们以二维噪声为例,如果我们想要得到二维的无缝Perlin噪声,就需要用四维噪声算法来产生。这种方法是思想是,由于我们想要每个维度都是无缝的,也就是当该维度的值从0变成1的过程中,0和1之间比较是平滑过渡的,这让我们想起了“圆”,绕圆一周就是对该维度的采样过程,这样就可以保证无缝了。因此,对于二维噪声中的x轴,我们会在四维空间下的xz平面上的一个圆上进行采样,而二维噪声的y轴,则会在四维空间下的yw平面上的一个圆上进行采样。这个转化过程很简单,我们只需要使用三角函数sin和cos即可把二维采样坐标转化到单位圆上。同样,三维空间的也是类似的,我们会在六维空间下计算。这种方法不仅适用于Perlin噪声,像Worley噪声这种也同样是适合的。 详细说明可以参考
。
Domain Warping
对上一篇fbm的拓展,可以制造出卷曲流动的效果,使用的公式是:
f(p) = fbm( p + fbm( p + fbm( p ) ) )
- Inigo Quiles (2002)明天分析一下这个Shader,最近看码得略微头痛...(maybe还是因为牙痛)
除夕啦,祝大家虎年快乐🐯!