有没有办法在 OpenGL 着色器中丢弃几何体、顶点或片段?

Is there a way to discard geometry, vertices or fragments in OpenGL shaders?

我正在使用实例渲染绘制大量立方体。现在,显然立方体中可见面的最大数量是 3,这意味着在阴影方面,我需要做的工作是需要的两倍。

因为这是实例化,所以我不能简单地将要绘制的几何体传递给着色器。但是如果在着色器中(我想这会在几何或曲面细分中)我可以使用法线信息来丢弃图元,我可以减少不必要的操作的数量。

例如,如果观察方向与表面法线之间的角度小于 90 度,我可以假设在当前三角形前面有一个三角形,从而丢弃这个给定的图元。

管道中有没有一种方法可以确定是否需要片段并相应地丢弃它?

回答问题之前,先解决你的实际问题:使用back-face culling。给每个立方体面的三角形一个一致的顺序,这样当从前面看时,屏幕 space 中面的顺序将是一种方式,但当从后面看时,顺序将是另一种方式。你选择哪一个是你的约定,但选择一个并保持一致。

然后使用 glFrontFace 告诉 OpenGL 哪个约定对你来说是 "front",并使用 glEnable(GL_CULL_FACE)glCullFace(GL_BACK) 告诉 OpenGL 剔除 back-facing 个三角形.

这种剔除是作为原始组装的一部分发生的,所以它早就过去了 vertex processing and post-processing

这就是您真正需要做的。哦,当然,您仍然将多达一半的顶点处理时间花在看不到的三角形上,但是如果您想剔除它们,您仍然需要花时间弄清楚是否要剔除它们。请记住:GPU 在 lock-step 中执行着色器调用。由于条件操作而剔除 triangles/faces/whatever 并不总能使任何事情变得更快,因为这些调用仍将继续执行。他们的结果将被丢弃。

面部剔除比您可以编写的任何代码都高效得多。


现在,让我们回答实际问题:shader-based 剔除有哪些选择?

您不能从顶点着色器中丢弃顶点。图元基于特定数量的顶点(GL_TRIANGLES 表示每组 3 个顶点是一个三角形),因此如果一个顶点被杀死,它将如何工作 non-functional.

您可以使用 user-defined 剔除 输出变量从顶点着色器中剔除三角形。这类似于 user-defined clipping planes,其中您的顶点着色器提供特殊的数字输出。对于裁剪,如果插值输出为正,则三角形的那部分是可见的;当插值变为负值时,三角形的那部分通过裁剪变为non-visible。

使用user-defined 剔除平面,如果特定图元的任何顶点具有负值剔除,则整个图元都将被剔除。这允许一个着色器调用通过给出一个负剔除值来选择剔除它所在的任何图元。

曲面细分控制着色器可以丢弃补丁。如果补丁的 TCS 结果为 zero value for any of the outer tessellation levels,那么他们正在处理的补丁将被曲面细分图元生成器剔除。

几何着色器当然可以完全不输出图元。