很久之前刚接触Perlin noise一直有个疑问,就是它的值域,看网上很多资料都默认是[-1,1],但是专门去找又说是根号2除以2,现在有时间来解决这个问题。
首先基本Perlin Noise的基本介绍不多说了,看这里的介绍:【图形学】谈谈噪声_worley噪声_妈妈说女孩子要自立自强的博客-CSDN博客
参考上面的图,假设求P点的值,Perline Noise的计算流程是:
1. 计算四个顶点处的梯度向量G
2. 计算从四个顶点到P的距离向量V,方向是周围顶点到P
3. 计算各个顶点点乘处G*V
4. P点在方框内的坐标做平滑
5. 使用4中计算的平滑后的坐标,对3中的结果做双线性插值。
根据之前的流程,可以求出各个顶点的距离向量为:
目的是为了求极值,所以不需要考虑坐标平滑。我们反推一下,既然P能取极值,那么四个顶点处的G*V都需要取极值,四个顶点处的距离向量我们已经求出来了,那么很显然当梯度G的方向和距离向量V同向时G*V最大,反向时G*V最小。
现在来推导G*V最大的情况,因为此时四个顶点的G和V同向,那么G*V就等同于求四个距离向量的模,即:
再根据P(x,y)点的坐标做双线性插值,这里不具体推导了,给出结果:
这个函数很复杂,求偏导数也很麻烦,所以这里直接把曲线画出来找极值点:
很明显函数是具有xy对称性的,并且在中间取得极大值,我们把P(0.5,0.5)带入上式,得到:
从而得到了正确的值域:
那么为什么很多资料认为值域是正负1呢,实际上是因为梯度向量G,按照Perline Noise的定义,这个G是需要归一化的,但总所周知归一化需要开根号,这个开销是比较大的,特别是需要实时生成大规模向量场的时候,所以在很多实际应用中,只会保证G向量的x和y都介于-1到1之间。此时意味着G的最大模变成了根号2,而不是1了,那意味着之前的计算结果都应该乘以根号2。从而得到: