我试图弄清楚如何为包含非平面多边形的网格正确实现平面着色(使用OpenGL / GLSL)。目的是获得类似于Blender给出的结果的东西(下面的所有多边形都是非平面的):



提供一些上下文信息-非平面多边形(例如四边形,五边形等)存在于我加载的网格中,或者是由于对网格应用细分方案(例如Catmull-Clark)而出现的。

三角形网格,我知道以下实现平面着色的方法—


在片段着色器中计算dFdxdFdy的叉积
使用几何着色器通过取三角形两侧的叉积来计算三角形法线
使用glDrawElements时,请使用flat插值限定符(基本上对所有片段使用与激发顶点相关的法线)
glDrawArrays,大多数顶点(通常是所有顶点)被多次复制到GPU。因此,每次可以使用不同的法线

对于包含非平面多边形的网格,前三个选项不会产生我想要的结果。在我的实现中(使用Qt框架),我使用GL_TRIANGLE_FAN



第四个选项可以工作,但不是很好-我想使用其中一个glDrawElementsglDrawMultiElements。另一种选择是使用glDrawElements,同时逐个循环遍历这些面孔(而不是使用glPrimitiveRestartIndex一次调用它)。在这种情况下,可以为每张脸上传一个uniform普通图像。但是,这似乎不是很有效。还有其他想法吗?

评论

有趣的问题。如果由于特定原因您不想要带有菱形十二面体的平面四边形形状,则提及该原因并解释使用非平面四边形的动机可能有助于洞悉所需的内容。

@trichoplax好,更新了问题:)。

您还可以为每个顶点指定一个法线作为一个属性,而不是一个均匀的对象,然后一次调用即可渲染网格。

#1 楼

不知道Blender的内部原理,我会说它对四边形使用共享法线,仅在四边形之间的边缘而不是在三角形之间对法线进行分割。因此,您要为每个四边形上载法线的想法可能与您要查找的结果接近。

如果将网格作为四边形加载,则已设置。如果使用的旧版OpenGL仍然存在四边形,则甚至可以使用解决方案3)。

如果将网格加载为三角形,则必须弄清楚哪些三角形起源四边形您可以通过在相邻三角形之间将分割法线强制超过固定角度来简单地做到这一点。

我不确定有没有简单的动态解决方案可以在其中渲染任何网格。您也许可以使用几何着色器查看相邻的顶点,但是最简单的版本是在上载之前平滑法线一次。