将透视投影矩阵(也称剪裁矩阵)乘以后,您将得到一个齐次的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 == near时的点。因此,如果您有一个由顶点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。
wc = (n * w1) + ((1 - n) * w2)
这一行?此外,您的投影矩阵P是右乘还是左乘,即v_e * P?更重要的是,我使用过的任何渲染器都不需要在绘制时指定近平面-当不知道近值时,如何执行此剪裁? - Qualiaw_3 = w_1 + r*(w_2-w_1)
和a_3 = a_1 + r*(a_2-a_3)
,其中a_n = dot(plane,v_n)
。但是a_3等于剪辑值w_3,因此a_1 + r*(a_2-a_1) = w_1 + r*(w_2-w_1)
。解出r,你就完成了。(希望如此)。 - Qualia