裁剪坐标系和标准化设备坐标系(OpenGL)中的裁剪
Posted
技术标签:
【中文标题】裁剪坐标系和标准化设备坐标系(OpenGL)中的裁剪【英文标题】:Clipping in clipping coordinate system and normalized device coordinate system (OpenGL) 【发布时间】:2017-06-13 11:06:25 【问题描述】:听说剪裁应该在剪裁坐标系中进行。 这本书提出了一种情况,即从相机后面到观看体积中铺设一条线。 (我们把这条线定义为PQ,P在相机点后面) 我不明白为什么会出现问题。
(书上说完成归一化变换后,P会放在镜头前。)
我认为在制作裁剪坐标系之前,相机在原点 (0, 0, 0, 1) 上,因为我们做了视图变换。 但是,在 NDCS 中,我无法考虑相机的位置。
我还有第二个问题。 在顶点着色器中,我们进行模型视图转换,然后进行投影转换。最后,我们将这些顶点输出到光栅化器。 (有些顶点的w不等于'1')
在这里,我很好奇。渲染管线会自动做除法(by w)吗?完成剪辑后。
【问题讨论】:
我建议你这样做:alfonse.bitbucket.io/oldtut? Nicol Bolas 的一本很棒的书/教程,您的所有问题都会很快得到解答。 我看了一点,但我认为没有任何我想要的信息。 OpenGL 只绘制坐标在 de 2x2x2 NDCS 内的像素。其他一切都被剪裁了。值模型 XYZ 坐标由矩阵 M、V、P 转换,生成的坐标分量“w”用于进行自动除法。 GPU 做的,不是你。 @Ripi2 非常感谢。如果你不介意,那么你能解释一下为什么剪裁应该在剪裁坐标中进行,而不是 NDCS。 当您有 4D 坐标(作为矩阵相乘的结果)时,像 3.0, 6.0, 12.0, 4.0 这样的点表示与 0.75, 1.5, 3.0, 1.0 相同的 3D 点。注意除以“w”。将“w”视为 4D 中的比例因子。因此,在透视分割之前,NDCS 2x2x2 立方体是 2wx2wx2wx。这是“剪裁空间”。驱动程序使用 if 进行剪裁,保存剪裁部分的分割。 【参考方案1】:有时无法在屏幕上看到所有模型,主要是因为它的某些对象位于相机后面(或“视角”)。那些对象被剪掉了。如果只是对象的一部分看不到,则必须只剪掉该部分,让其余部分保持可见。
OpenGL 剪辑
OpenGL 在剪切坐标空间 (CCS) 中进行这种剪切。这是一个大小为 2w x 2w x 2w 的立方体,其中“w”是 (4x4) x (4x1) 矩阵和点乘法的第四个坐标。仅仅比较坐标就足以判断该点是否被裁剪。如果该点通过测试,则其坐标除以“w”(所谓的“透视除法”)。请注意,对于正交投影,“w”始终为 1,而透视通常不是 1。
CPU 剪辑
如果模型太大,您可能希望节省 GPU 资源或提高帧速率。所以你决定跳过那些无论如何都会被剪裁的对象。然后您自己(在 CPU 上)进行数学运算,仅将通过测试的顶点发送到 GPU。请注意,某些对象可能会裁剪某些顶点,而同一对象的其他顶点可能不会。 也许您确实将它们发送到 GPU 并让它处理这些特殊情况。
您定义了一个体积,其中只能看到内部的对象。该体积由六个平面定义。让我们把自己放在相机里看看这个体积:如果你的投影是透视的,那么六个平面会构建一个“fustrum”,一种截断的金字塔。如果您的投影是正交的,则这些平面形成一个平行六面体。
为了剪裁或不剪裁顶点,您必须使用顶点到这六个平面中的每一个的距离。您需要一个有符号的距离,这意味着该符号告诉您从顶点可以看到平面的哪一侧。如果六个距离符号中的任何一个不是正确的,则该顶点被丢弃、剪裁。
如果平面由方程 Ax+By+Cz+D=0 定义,则到 p1,p2,p3 的有符号距离为 (Ap1+Bp2+Cp3+D)/sqrt(AA+BB+C*C)。你只需要符号,所以不用计算分母。
现在您拥有所有工具。如果您知道“相机视图”上的平面,则可以计算六个距离并剪裁或不剪裁顶点。但考虑到您必须将顶点坐标从模型转换到相机(视图)空间,这可能是一项昂贵的操作,这是一种 ViewModel 矩阵计算。以相同的成本,您可以使用预先计算的 ProjectionViewModel 矩阵来获取 CCS 坐标,这与 CCS 立方体的大小“2w”相比更容易。
有时您想要跳过某些顶点不是因为它们被剪裁,而是因为它们的深度破坏了您使用的标准。在这种情况下,CCS 不是合适的工作空间,因为 Z 坐标被转换为 [-w, w] 范围,深度不知何故“丢失”。相反,您在“视图空间”中进行剪辑测试。
【讨论】:
以上是关于裁剪坐标系和标准化设备坐标系(OpenGL)中的裁剪的主要内容,如果未能解决你的问题,请参考以下文章