使用单纯形噪声替换的球体的解析法线

Gig*_*igo 5 opengl glsl normals simplex-noise

我想渲染一个像球体一样的行星.总体思路如下:

  • 生成一组构成球体的单位长度顶点.
  • 渲染球体时,着色器会评估单位球面上的3D单面噪声.
  • 结果用作"高度"以沿其方向移动当前顶点.

到目前为止,一切都正常运作.

现在我想添加光照,因此需要法线到表面.

在实现与照明相关的部分时,我快速添加了一种方法,使用片段着色器中的偏导数来估计地形的法线,如下所示:

vec3 X = dFdx(ins.position);
vec3 Y = dFdy(ins.position);
vec3 normal = normalize(cross(X,Y));
Run Code Online (Sandbox Code Playgroud)

ins.position插值世界位置在哪里.

虽然这种方法有效,但它看起来并不是很好,因为它实际上导致了每个面的法线.

不正常的近似值

现在来看实际问题:

  • 计算每顶点法线会导致平滑法线,与图片不同,是否正确?
  • 单因素噪声优于Perlin噪声的优点之一是具有"定义明确且连续的梯度,可以非常便宜地计算"(引用优秀的单纯形噪声揭秘),并且梯度应该能够计算正常,对吗?

如果秒问题是"是",我有两个问题:

  • 单纯噪声算法取自一个流行的来源,遗憾的是不包括梯度计算.我将在下面发布我的添加尝试,但我不知道它是否正确.
  • 即使我有渐变,我仍然坚持从那里获得法线.

任何帮助是极大的赞赏!

我在渐变实现中的镜头(替换了最后几行的snoise):

float snoise(vec3 v, out vec3 grad)
{
    ......

    // Mix final noise value
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
    vec4 m2 = m * m;
    vec4 m4 = m2 * m2;

    vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3));

    vec4 temp = m2 * m * pdotx;
    grad = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3);
    grad += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3;
    grad *= 42.0;

    return 42.0 * dot(m4, pdotx);
}
Run Code Online (Sandbox Code Playgroud)

更新:

关于从梯度计算表面法线的部分已在此处得到解答: 曲面法线指向位移球面上的点.

现在剩下的问题是如何将梯度计算实现到3D Simplex Noise的GLSL版本中,因为我的实现似乎有问题.

更新2:

渐变计算似乎几乎是正确的,只是缩放似乎是关闭的.
除了乘以42,除以5得到相当好的结果,但这是通过反复试验找到的.适当的缩放因子会很好.

Gig*_*igo 3

好吧,事实证明我的问题几乎纯粹与数学相关。

如果有人感兴趣:
问题中发布的梯度计算的 GLSL 实现是完全正确的。如此
处所述,可以直接从梯度计算法线。

结果看起来和我想要的一模一样,我很高兴;)

平滑每个顶点法线