【问题标题】:How to do bilinear interpolation of normals over a quad?如何在四边形上对法线进行双线性插值?
【发布时间】:2012-02-12 03:25:14
【问题描述】:

我正在开发一个类似 Minecraft 的引擎作为一个爱好项目,看看体素地形的概念可以在现代硬件和 OpenGL >= 3 上推动多远。所以,我所有的几何体都由四边形或正方形组成准确一点。

我已经构建了一个光线投射器来估计环境光遮蔽,并使用“弯曲法线”技术来进行照明。所以我的法线不垂直于四边形,也没有单位长度;相反,它们大致指向发生遮挡最少的空间,并且当四边形接收到较少的光时更短。这种技术的优点是它只需要一次性计算遮挡,并且在渲染时基本上是免费的。

但是,当我尝试将不同的法线分配给同一个四边形的不同顶点以获得平滑照明时,我遇到了麻烦。因为四边形被分割成三角形,并且线性插值发生在每个三角形上,插值的结果清楚地表明三角形的存在是丑陋的对角线伪影:

问题在于 OpenGL 对每个三角形使用重心插值,这是 4 个角中 3 个角的加权和。理想情况下,我想使用双线性插值,其中所有 4 个角都用于计算结果。

我能想到一些解决方法:

  1. 将法线填充到 2x2 RGB 纹理中,并让纹理处理器进行双线性插值。这是以片段着色器中的纹理查找为代价的。为了提高效率,我还需要将所有这些迷你纹理打包成更大的纹理。

  2. 使用顶点属性将所有 4 个法线附加到每个顶点。还将一些 [0..1] 系数附加到每个顶点,就像纹理坐标一样,并在片段着色器中进行双线性插值。发生这种情况的代价是向着色器传递了 4 个法线,而不仅仅是 1 个。

我认为这两种技术都可以发挥作用,但它们让我觉得它们是一些应该更简单的东西的组合。也许我可以以某种方式转换法线,这样 OpenGL 的插值就会给出一个不依赖于所使用的特定三角剖分的结果。

(请注意,该问题并非特定于法线;它同样适用于需要在四边形上平滑插值的颜色或任何其他值。)

任何想法如何解决这个问题?如果不是,上述两种技术中的哪一种最好?

【问题讨论】:

  • GL_QUADS 在 opengl 3 中已弃用

标签: opengl glsl interpolation


【解决方案1】:

正如您清楚地了解的那样,GL 所做的三角形插值并不是您想要的。 所以法线数据不能直接来自顶点数据。

恐怕您所设想的解决方案是您可以实现的最佳解决方案。而且无论您选择什么,您都需要将 [0..1] 系数从顶点传递到着色器(包括 2x2 纹理。您需要它们作为纹理坐标)。

不过,您可以采取一些技巧来简化流程。

  • 使用顶点 ID 可以帮助您找到从顶点传递到片段着色器的顶点“角”(我们的 [0..1] 值)。对最低 2 位进行简单的位测试可以让您知道要通过哪个角,而无需输入实际的顶点数据。如果打包纹理数据,您仍然需要在纹理内部传递一个标识符,所以这可能没有实际意义。
  • 如果您使用 2x2 纹理来允许插值,则存在(曾经?)一些陷阱。如果源一开始就处于低精度,则某些纹理插值器不一定提供高精度插值。这可能需要您将纹理数据类型更改为更高精度以避免条带伪影。

【讨论】:

    【解决方案2】:

    嗯...当您使用弯曲法线技术时,增加结果的最佳方法是预先细分网格并使用具有更高细分的网格重新计算。

    另一种方法是像素着色器中的一些技巧......一种可能的方法 - 您实际上可以在像素着色器中自行插入纹理(而不是使用内置插值器),这对您有很大帮助。而且您不仅限于双线性插值,还可以做得更好,F.e.双三次插值 ;)

    【讨论】:

    • 我不想增加网格密度,因为我试图推出尽可能多的块。我知道如何自己插入纹理,但如果我能提供帮助,我不想将我的法线存储在纹理中——因此这个问题!
    猜你喜欢
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多