3D Perlin 噪声分析导数 [英] 3D Perlin noise analytical derivative

查看:24
本文介绍了3D Perlin 噪声分析导数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用 Shader Model 4 (DirectX 10 HLSL) 实现 3D Perlin 噪声凹凸贴图.生成噪声本身并不是一个大问题(周围有大量的教程和代码),但我还没有找到 3D Perlin 噪声的分析导数.

I am currently implementing a 3D Perlin noise bump mapping using Shader Model 4 (DirectX 10 HLSL). Generating the noise itself is not a big problem (there are tons of tutorials and codes around) but what I have not found are analytical derivatives of 3D Perlin noise.

唯一考虑衍生品的网站是Ińigo Quilez 的网站和相关的GameDev.net 讨论.问题是在第一个链接中,噪声是基于值的,而不是基于梯度的(这是我的要求),在第二个链接中,只有二维梯度噪声导数.

The only sites taking the derivatives into account are Ińigo Quilez's site and a related GameDev.net discussion. The problem is that in the first link the noise is value based, not gradient based (which is a requirement for me), in the second link, there's only 2D gradient noise derivative.

请注意,我不是在寻找数值导数,因为它们需要生成 4 个相邻的噪声样本,而且开销太大.

Note that I'm not looking for numerical derivatives as those require 4 neighboring noise samples to be generated and that's way too much overhead.

有人计算过这些导数吗?是否有使用它们的参考实现?

Has anyone calculated these derivatives? Is there a reference implementation that is using them?

推荐答案

我今天在网上也找不到解决方案,所以我试着推导一下.

I also could not found a solution on the web today, so I tried to derive it.

首先定义 3D Perlin 噪声的符号.

Firstly the notations of a 3D Perlin noise is defined.

假设 3D Perlin 噪声是通过三线性插值计算的

Assume the 3D Perlin noise is computed by the trilinear interpolation as

n = Lerp(
        Lerp(
            Lerp(dot000, dot100, u),
            Lerp(dot010, dot110, u),
            v), 
        Lerp(
            Lerp(dot001, dot101, u), 
            Lerp(dot011, dot111, u),
            v),
        w)

其中uvw是分数坐标五次多项式的插值因子(即改进的Perlin噪声):

where u, v, w are the interpolation factors by the quintic polynomial of fraction coordinates (i.e., improved Perlin noise):

x0 = frac(x)
y0 = frac(y)
z0 = frac(z)
x1 = x0 - 1
y1 = y0 - 1
z1 = z0 - 1

u = x0 * x0 * x0 * (x0 * (6 * x0 - 15) + 10)
v = y0 * y0 * y0 * (y0 * (6 * y0 - 15) + 10)
w = z0 * z0 * z0 * (z0 * (6 * z0 - 15) + 10)

dot___s是梯度向量(gx___, gy___, gz___)s在格点和分数坐标的点积:

and dot___s are dot products of the gradient vectors (gx___, gy___, gz___)s at lattice points and the fraction coordinates:

dot000 = gx000 * x0 + gy000 * y0 + gz000 * z0
dot100 = gx100 * x1 + gy100 * y0 + gz100 * z0
dot010 = gx010 * x0 + gy010 * y1 + gz010 * z0
dot110 = gx110 * x1 + gy110 * y1 + gz110 * z0
dot001 = gx001 * x0 + gy001 * y0 + gz001 * z1
dot101 = gx101 * x1 + gy101 * y0 + gz101 * z1
dot011 = gx011 * x0 + gy011 * y1 + gz011 * z1
dot111 = gx111 * x1 + gy111 * y1 + gz111 * z1

计算导数

首先计算uvw

u' = 30 * x0 * x0 * (x0 - 1) * (x0 - 1)
v' = 30 * y0 * y0 * (y0 - 1) * (y0 - 1)
w' = 30 * z0 * z0 * (z0 - 1) * (z0 - 1)

通过用 Lerp(a, b, t) = a + (b - a) * t,

n = dot000 
  + u(dot100 - dot000)
  + v(dot010 - dot000)
  + w(dot001 - dot000)
  + uv(dot110 - dot010 - dot100 + dot000)
  + uw(dot101 - dot001 - dot100 + dot000)
  + vw(dot011 - dot001 - dot010 + dot000)
  + uvw(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000)

然后取n的偏导数,

nx = gx000
   + u'  (dot100 - dot000)
   + u   (gx100 - gx000)
   + v   (gx010 - gx000)
   + w   (gx001 - gx000)
   + u'v (dot110 - dot010 - dot100 + dot000)
   + uv  (gx110 - gx010 - gx100 + gx000)
   + u'w (dot101 - dot001 - dot100 + dot000)
   + uw  (gx101 - gx001 - gx100 - gx000)
   + vw  (gx011 - gx001 - gx010 + gx000)
   + u'vw(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000)
   + uvw (gx111 - gx011 - gx101 + gx001 - gx110 + gx010 + gx100 - gx000)

,

ny = gy000
   + u   (gy100 - gy000)
   + v'  (dot010 - dot000)
   + v   (gy010 - gy000)
   + w   (gy001 - gy000)
   + uv' (dot110 - dot010 - dot100 + dot000)
   + uv  (gy110 - gy010 - gy100 + gy000)
   + uw  (gy101 - gy001 - gy100 + gy000)
   + v'w (dot011 - dot001 - dot010 + dot000)
   + vw  (gy011 - gy001 - gy010 + gy000)
   + uv'w(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000)
   + uvw (gy111 - gy011 - gy101 + gy001 - gy110 + gy010 + gy100 - gy000)

,

nz = gz000
   + u   (gz100 - gz000)
   + v   (gz010 - gz000)
   + w'  (dot001 - dot000)
   + w   (gz001 - gz000)
   + uv  (gz110 - gz010 - gz100 + gz000)
   + uw' (dot101 - dot001 - dot100 + dot000)
   + uw  (gz101 - gz001 - gz100 + gz000)
   + vw' (dot011 - dot001 - dot010 + dot000)
   + vw  (gz011 - gz001 - gz010 + gz000)
   + uvw'(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000)
   + uvw (gz111 - gz011 - gz101 + gz001 - gz110 + gz010 + gz100 - gz000)

那么(nx, ny, nz)就是噪声函数的梯度向量(偏导数).

Then (nx, ny, nz) is the gradient vector (partial derivatives) of the noise function.

一些常见的子表达式可以被分解出来,如果编译器不能处理它.例如:

Some common sub-expression can be factored out, if the compiler cannot handle it. For example:

uv = u * v
vw = v * w
uw = u * w
uvw = uv * w

扩展后的n中的系数被多次重复使用.它们可以通过以下方式计算:

The coefficients in the expanded n are reused multiple times. They can be computed by:

k0 = dot100 - dot000
k1 = dot010 - dot000
k2 = dot001 - dot000
k3 = dot110 - dot010 - k0
k4 = dot101 - dot001 - k0
k5 = dot011 - dot001 - k1
k6 = (dot111 - dot011) - (dot101 - dot001) - k3

而且导数也有相似的系数,

Also the derivatives has similar coefficients,

gxk0 = gx100 - gx000
gxk1 = gx010 - gx000
...

n 的计算也可以使用k0, ... k6 的扩展形式.

The computation of n can uses the expanded form with k0, ... k6 as well.

此解已通过中心差分法验证.

This solution has been verified against central difference method.

虽然这个解决方案看起来很笨拙,但我的实验(仅限 CPU,SSE)表明,通过这个解决方案计算这些导数只需要 50% 的额外时间来计算单个 3D Perlin 噪声样本.

Although this solution looks clumsy, my experiment (CPU only, SSE) showed that, computing these derivatives by this solution only incurs about 50% extra time to computing a single 3D Perlin noise sample.

有限差分至少需要 300% 的额外时间(做额外 3 个样本)或 600%(做 6 个样本进行中心差分).

Finite difference will at least need 300% extra time (doing extra 3 samples) or 600% (doing 6 samples for central difference).

因此,该解决方案在性能上更好,并且在数值上也应该更稳定.

Therefore, this solution is better in performance, and should also be more numerically stable.

这篇关于3D Perlin 噪声分析导数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆