Perlin noise的值域

        很久之前刚接触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中的结果做双线性插值。

         根据之前的流程,可以求出各个顶点的距离向量为:

\vec {AP} = (x,y),\vec {BP} = (x-1,y),\vec {CP} = (x,y-1),\vec {DP} = (x-1,y-1)

        目的是为了求极值,所以不需要考虑坐标平滑。我们反推一下,既然P能取极值,那么四个顶点处的G*V都需要取极值,四个顶点处的距离向量我们已经求出来了,那么很显然当梯度G的方向和距离向量V同向时G*V最大,反向时G*V最小。

        现在来推导G*V最大的情况,因为此时四个顶点的G和V同向,那么G*V就等同于求四个距离向量的模,即:

\newline \vec {\left |AP \right |}=\sqrt{x^2+y^2} ,\newline \vec {\left |BP \right |}=\sqrt{(x-1)^2+y^2} ,\newline \vec {\left |CP \right |}=\sqrt{x^2+(y-1)^2} ,\newline \vec {\left |DP \right |}=\sqrt{(x-1)^2+(y-1)^2}

        再根据P(x,y)点的坐标做双线性插值,这里不具体推导了,给出结果:

\newline P(x,y) = \sqrt{x^2+y^2}*(1-x)(1-y)) + \newline \sqrt{(x-1)^2+y^2}*x(1-y)) + \newline \sqrt{x^2+(y-1)^2}*(1-x)y) + \newline \sqrt{(x-1)^2+(y-1)^2}*xy)

        这个函数很复杂,求偏导数也很麻烦,所以这里直接把曲线画出来找极值点:

        很明显函数是具有xy对称性的,并且在中间取得极大值,我们把P(0.5,0.5)带入上式,得到:

P(0.5,0.5) = \frac {\sqrt{2}}{2}

        从而得到了正确的值域:

        P(x,y) \in = [-\frac {\sqrt{2}}{2}, \frac {\sqrt{2}}{2}]

        那么为什么很多资料认为值域是正负1呢,实际上是因为梯度向量G,按照Perline Noise的定义,这个G是需要归一化的,但总所周知归一化需要开根号,这个开销是比较大的,特别是需要实时生成大规模向量场的时候,所以在很多实际应用中,只会保证G向量的x和y都介于-1到1之间。此时意味着G的最大模变成了根号2,而不是1了,那意味着之前的计算结果都应该乘以根号2。从而得到:

P(x,y) \in = [-1, 1],G.x\in (-1,1),G.y\in (-1,1)

猜你喜欢

转载自blog.csdn.net/paserity/article/details/129711228