裁剪坐标系和归一化设备坐标系(OpenGL)中的裁剪

Clipping in clipping coordinate system and normalized device coordinate system (OpenGL)

听说裁剪应该在裁剪坐标系下进行。 这本书提出了一种情况,即一条线从相机后面铺设到观看空间。 (我们把这条线定义为PQ,P在camera point后面) 我不明白为什么这会成为问题。

(书上说归一化后,P会放在镜头前。)

我想在制作裁剪坐标系之前,相机在原点(0, 0, 0, 1)上,因为我们做了观察变换。 但是,在 NDCS 中,我无法考虑相机的位置。

我还有第二个问题。 在顶点着色器中,我们进行模型-视图变换,然后进行投影变换。最后,我们将这些顶点输出到光栅化器。 (某些顶点的w不等于'1')

这里,我有好奇心。渲染管线会自动做除法(by w)?剪辑完成后。

有时并不是所有的模型都能在屏幕上看到,主要是因为它的一些物体位于相机后面(或"point of view")。那些对象被剪掉了。如果只是物体的一部分看不到,则必须只剪掉该部分,让其余部分保持可见。

OpenGL 剪辑

OpenGL 在裁剪坐标 Space (CCS) 中进行裁剪。这是一个大小为 2w x 2w x 2w 的立方体,其中 'w' 是 (4x4) x (4x1) 矩阵和点乘法的第四个坐标。仅仅比较坐标就足以判断该点是否被裁剪。如果该点通过测试,则其坐标除以 'w'(所谓的 "perspective division")。请注意,对于正交投影,'w' 始终为 1,而透视通常不是 1。

CPU 剪辑

如果模型太大,也许你想节省 GPU 资源或提高帧率。所以你决定跳过那些无论如何都会被剪裁的对象。然后你自己做数学运算(在 CPU 上)并且只将通过测试的顶点发送给 GPU。请注意,某些对象可能会剪裁某些顶点,而同一对象的其他顶点可能不会。 也许您确实将它们发送给 GPU 并让它处理这些特殊情况。

您定义了一个体积,其中只能看到内部的物体。该体积由六个平面定义。让我们把自己放在相机里,看看这个体积:如果您的投影是透视的,那么六个平面会构建一个 "fustrum",一种截角金字塔。如果您的投影是正交的,则平面形成平行六面体。

为了裁剪或不裁剪顶点,您必须使用从顶点到这六个平面中的每一个的距离。您需要一个带符号的距离,这意味着该符号告诉您从顶点可以看到平面的哪一侧。如果六个距离标志中的任何一个不正确,则该顶点被丢弃、裁剪。

如果平面由方程 Ax+By+Cz+D=0 定义,则与 p1、p2、p3 的符号距离为 (Ap1+Bp2+Cp3+D)/sqrt(A A+BB+C*C)。只需要符号,不用计算分母

现在你拥有了所有的工具。如果您知道 "camera view" 上的平面,您可以计算六个距离并裁剪或不裁剪顶点。但考虑到您必须将顶点坐标从模型转换为摄像机(视图)spaces,即 ViewModel 矩阵计算,这可能是一项昂贵的操作。以相同的成本,您可以使用预先计算的 ProjectionViewModel 矩阵来获取 CCS 坐标,这与“2w”(CCS 立方体的大小)相比更容易。

有时您想要跳过某些顶点不是因为它们被剪裁了,而是因为它们的深度违反了您正在使用的标准。在这种情况下,CCS 不适合使用 space,因为 Z-coordinate 被转换为 [-w, w] 范围,深度不知何故 "lost"。相反,您在 "view space".

中进行剪辑测试