opengl 中的面部剔除是否发生在窗口空间中?

Rou*_*bin 2 opengl graphics gpu opengl-es

顶点后处理的输出值在窗口空间中,那么我们有图元组装和面部剔除阶段。如果是在窗口空间中进行面部剔除?

der*_*ass 5

让我引用OpenGL 4.6 核心配置文件规范,第 1.2.3 节“什么是 OpenGL 图形系统?| 我们的观点”(强调我的观点):

我们将 OpenGL 视为具有一些可编程阶段和一些由一组特定绘图操作调用的状态驱动的固定功能阶段的管道。这个模型应该产生一个满足程序员和实现者需求的规范。然而,它不一定提供实施模型。实现必须产生与指定方法产生的结果一致的结果,但执行特定计算的方法可能比指定方法更有效。

这意味着如果实现与完全遵循规范逐字逐句的实现相同的结果,则实现是符合要求的。

因此,面部剔除的行为方式必须与在窗口空间中进行的方式相同。它显然顶点着色器阶段,因为在此之前,顶点的最终坐标是未知的。(现在这里有一个有趣的旁注。它是 iirc nvidia,它拥有将顶点着色器分成两部分的专利:在其中只计算gl_Position并且可以优化所有对你没有贡献的计算,一个用于其余的输出。这将允许他们只执行 VS 的一部分来进行裁剪和剔除。不确定他们是否真的采用了这种策略在他们的驱动程序中,但专利在某处。然而,这是一个很好的例子,说明现实世界的实现可能会做什么奇怪的技巧。)

那么人脸剔除会发生在窗口空间中吗?只有您的 OpenGL 实现者才能确定。但换个角度思考能否在剪辑空间中实现面部剔除?

首先,让我们看看它是否可以发生在规范化的设备空间中

显然,对于面剔除,只有三角形的 2D 投影的缠绕顺序重要,所以 z 无关紧要。当你从剪辑空间转到窗口空间时,这个方向不会改变,或者是吗?这里有一些观察:

  • 在NDC到窗口空间转换只是一个缩放和平移,每个组件单独工作,我们没有得到形式的交叉影响x_win = A * x_ndc + B *y_ndc + c * z_ndc + D,但BC保证是0这里。
  • 因此,当从裁剪空间到窗口空间时,翻转三角形方向的唯一方法是如果比例因子为负,并在glViewport*()函数系列中再次引用 GL 4.6 规范:“INVALID_VALUE如果 w 或 h 为负,则会生成错误”

这意味着面部剔除可以在 NDC 中完成,而不必考虑实际的视口参数。

面部剔除可以在剪辑空间中发生吗?

  • 任何一点w<0都不可能满足裁剪条件-w <= x,y,z <= w,因此从裁剪空间到 NDC 的 w 步除只会发生,w>0因此永远不会翻转三角形。但这要求至少原始裁剪已经发生(考虑一个顶点位于相机后面,两个顶点位于相机前面的情况)。
  • 然而,w即使在裁剪之后坐标仍然很棘手。考虑这样一种情况:您站在天花板倾斜的房间里,直视侧壁,但看到天花板的一部分。天花板上的三角形可能会导致以下剪辑空间坐标(-1,1,z_1,1), (1,1,z_2,1), (0,1.2,z_3,10)(有些z_is 满足剪辑条件,实际值在这里无关紧要)。如果您只采用剪辑空间xy值(就像在窗口空间或 NDC 中所做的那样),您将看到第三个顶点位于前两个顶点形成的线上方的 2D 投影。但是在除以 之后w,它将低于,并且三角形顺序被翻转(因为w每个顶点可能会有所不同)。

那么这是否意味着在透视除以之前不能进行面部剔除w?不,不一定。也许有一些聪明的方法可以在分割之前在剪辑空间中进行剔除,但无论哪种方式,剪辑空间w坐标都需要以某种方式被考虑在内

所以我不能真正回答你的问题,但一般原则是实现者尽可能早地在管道中进行任何类型的剔除/丢弃步骤(当然,在他们将拥有的所有工程限制范围内)。