如何在四边形上进行法线的双线性插值?

时间:2012-02-11 12:36:07

标签: opengl glsl interpolation

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

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

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

Diagonal lines visible in the rendered result

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

我可以想到一些解决方法:

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

  2. 使用顶点属性将所有4个法线附加到每个顶点。还将一些[0..1]系数附加到每个顶点,非常类似于纹理坐标,并在片段着色器中进行双线性插值。这是以将4个法线传递给着色器而不是仅仅1来为代价的。

  3. 我认为这两种技术都可以发挥作用,但它们让我觉得它应该更简单。也许我可以用某种方式转换法线,这样OpenGL的插值就会得到一个不依赖于特定三角测量的结果。

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

    有什么想法可以解决这个问题吗?如果没有,上述两种技术中哪一种最好?

2 个答案:

答案 0 :(得分:4)

正如您清楚地了解的那样,GL将执行的三角插值不是您想要的。 所以普通数据不能直接来自顶点数据。

我担心你想象的解决方案是你能达到的最好的解决方案。无论你选择什么,你都需要将[0..1]系数从顶点传递到着色器(包括2x2纹理。你需要它们用于纹理坐标)。

但是,您可以采取一些措施来简化流程。

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

答案 1 :(得分:0)

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

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