【问题标题】:Analytic normals to a sphere displaced with Simplex Noise用单纯形噪声置换的球体的解析法线
【发布时间】:2023-03-10 00:06:01
【问题描述】:

我想渲染一个类似球体的行星。大致思路如下:

  • 生成一组构成球体的单位长度顶点。
  • 在渲染球体时,着色器会评估单位球体上点处的 3D 单纯形噪波。
  • 结果用作“高度”以沿其方向置换当前顶点。

到目前为止,一切正常。

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

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

vec3 X = dFdx(ins.position);
vec3 Y = dFdy(ins.position);
vec3 normal = normalize(cross(X,Y));

其中ins.position 是插值后的世界位置。

虽然这可行,但它看起来不是很好,因为它本质上会产生每个面的法线。

现在是实际问题:

  • 计算每个顶点的法线会产生平滑的法线,这与图片不同,对吗?
  • Simplex 噪声相对于 Perlin 噪声的优点之一是“在任何地方都有一个定义明确且连续的梯度,可以非常便宜地计算”(引用优秀的 Simplex Noise demystified)并且使用梯度应该能够计算正常,对吗?

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

  • 单纯形噪声算法取自popular source,遗憾的是它不包括梯度计算。我将在下面发布我添加它的尝试,但我不知道它是否正确。
  • 即使我有渐变,我仍然坚持从那里导出法线。

非常感谢任何帮助!

我对渐变实现的看法(替换了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);
}

更新:

这里已经回答了关于从梯度计算表面法线的部分: Surface normal to point on displaced sphere.

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

更新 2:

梯度计算似乎几乎正确,只是缩放似乎关闭了。
不是乘以 42,而是除以 5 会得到很好的结果,但这是通过反复试验发现的。适当的比例因子会很好。

【问题讨论】:

  • 回答您的第一个问题:是和否。如果您有关于相邻三角形的信息,每个顶点法线可以是平滑的,或者如果您使用单个三角形计算它们,它们可以是平坦的。使用几何着色器和具有邻接关系的三角形条带,每个顶点最多可以得到 4 个共享三角形,这 可能(考虑到实际上 不是每个顶点所属的三角形的数量)足以计算近似平滑的每个顶点法线。您必须以非常特殊的顺序构建输入顶点索引才能完成此操作,并且需要 GL 3.2+。
  • 如果我理解正确,如果给定顶点的法线相同,则无论当前处理什么面,生成的法线都将是平滑的。假设计算按照我描述的方式进行,情况就是这样,因为法线将仅取决于它们所属的单个顶点的信息。
  • 嗯,每个顶点的(平滑)法线取决于共享该顶点的每个三角形中的其他 2 个顶点。我查看了您的网格并注意到一些顶点具有多达 10 个共享相同顶点的三角形。如果您想正确地平滑这些每个顶点的法线,则必须计算所有 10 个三角形的面法线。这就是为什么它看起来不实用。
  • 您可以通过dFdx 和dYdx 在片段着色器中使用 GPU 计算的渐变调整球面法线来避免此问题。
  • @Justin 你的意思是像我在问题中描述的那样吗? ;)

标签: opengl glsl normals simplex-noise


【解决方案1】:

好吧,原来我的问题几乎与数学有关。

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

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

【讨论】:

  • 你能分享一些代码吗?我无法像你描述的那样让它工作。
  • 我会尝试把这个项目挖出来放到 Github 上。
  • 那太好了:D
猜你喜欢
  • 2011-09-20
  • 1970-01-01
  • 2013-08-22
  • 2012-01-14
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
相关资源
最近更新 更多