乘以透视投影矩阵(又名剪辑矩阵)后,您将得到一个齐次的 4 向量 [x,y,z,w]。这称为 npc(归一化投影坐标),也称为剪辑坐标。要在屏幕上获取 2D 坐标,您通常使用类似的东西
xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width
对于相机前面的点,这可以满足您的需求。但是相机后面的点将具有 w<0 并且即使该点位于相机后面,您也会得到映射到有效屏幕坐标的值。为避免这种情况,您需要进行剪辑。任何具有 w<0 的顶点都需要被剪裁。
一个快速的尝试是,如果任一顶点的 w<0,则不画任何线。这应该可以修复场景中出现的奇怪多边形。但它也会删除一些应该可见的线条。
要完全解决这个问题,您需要剪裁所有在相机前面有一个顶点和在相机后面有一个顶点的线。剪辑意味着将线切成两半并扔掉相机后面的一半。这条线被穿过相机并与显示屏平行的平面“剪裁”。问题是在直线上找到与该平面相对应的点(即直线与平面相交的位置)。这将发生在线上 w==0 的点。你可以找到这个点,但是当你试图找到屏幕坐标时
xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width
你最终除以 0 (w==0)。这就是“近剪裁平面”的原因。近剪裁平面也平行于显示屏,但位于相机前面(相机和场景之间)。相机和近剪裁平面之间的距离是投影矩阵的“近”参数:
[ near/width ][ 0 ][ 0 ][ 0 ]
[ 0 ][ near/height ][ 0 ][ 0 ]
[ 0 ][ 0 ][(far+near)/(far-near) ][ 1 ]
[ 0 ][ 0 ][-(2*near*far)/(far-near)][ 0 ]
要裁剪到近平面,您必须找到与近裁剪平面相交的线上的点。这是 w == 附近的点。因此,如果您有一条带有顶点 v1,v2 的线,其中
v1 = [x1, y1, z1, w1]
v2 = [x2, y2, z2, w2]
您需要检查每个顶点是在近剪裁平面的前面还是后面。如果 w1 >= near,则 V1 在前面,如果 w1 < near,则 V1 在后面。如果 v1 和 v2 都在前面,则画线。如果 v1 和 v2 都在后面,则不要画线。如果 v1 在前面而 v2 在后面,那么您需要找到 vc 直线与近裁剪平面相交的位置:
n = (w1 - near) / (w1 - w2)
xc = (n * x1) + ((1-n) * x2)
yc = (n * y1) + ((1-n) * y2)
zc = (n * z1) + ((1-n) * z2)
wc = near
vc = [xc, yc, zc, wc]
现在画出 v1 和 vc 之间的界限。