Graphics 三维透视投影的剪辑矩阵

Graphics 三维透视投影的剪辑矩阵,graphics,3d,matrix,projection,clip,Graphics,3d,Matrix,Projection,Clip,我正在尝试创建一个简单的3D图形引擎,并且已经找到并使用了我在这里找到的方程式:。(我有Dx、Dy、Dz和Bx的计算,由) 我可以工作,但当我旋转相机时,足够多的线开始在整个地方飞来飞去,最终你会看到离开屏幕的多边形开始回到屏幕的另一侧(你可以到这里:使用W、A、S和D键旋转相机,看看我在说什么) 我读了这篇讨论:在那里他谈到了使用剪辑矩阵,但对于如何准确使用剪辑矩阵,我还是有点困惑。此外,我不确定是否使用了讨论中描述的“齐次坐标”。这可能是对术语的误解。剪辑矩阵更恰当地称为投影矩阵。至少在Op

我正在尝试创建一个简单的3D图形引擎,并且已经找到并使用了我在这里找到的方程式:。(我有Dx、Dy、Dz和Bx的计算,由)

我可以工作,但当我旋转相机时,足够多的线开始在整个地方飞来飞去,最终你会看到离开屏幕的多边形开始回到屏幕的另一侧(你可以到这里:使用W、A、S和D键旋转相机,看看我在说什么)


我读了这篇讨论:在那里他谈到了使用剪辑矩阵,但对于如何准确使用剪辑矩阵,我还是有点困惑。此外,我不确定是否使用了讨论中描述的“齐次坐标”。

这可能是对术语的误解。剪辑矩阵更恰当地称为投影矩阵。至少在OpenGL中,投影矩阵将视图坐标空间(VCS)中的4D齐次坐标变换为剪裁坐标空间(CCS)。从CCS到标准化设备坐标空间(NDCS)的投影需要透视分割,即用W分量分割每个分量。在此步骤之前已正确完成剪裁。因此,“剪裁矩阵”不会消除在投影之前剪裁几何体的需要。我希望我已经理解了你的意思,这听起来不像是居高临下


这就是说,我认为你显然把投影矩阵做对了——它是有效的。我怀疑通过眼睛后面的顶点有负W,这意味着它们应该被剪裁;但我也怀疑它们有负Z,所以除法得到的是正Z值。如果确实要剪裁几何体,而不是放弃整个三角形,请搜索“齐次剪裁”。如果你不是真的在4D均匀空间中工作,你可以先看一下“Sutherland Hodgman”的3D剪辑。

在乘以透视投影矩阵(又称剪辑矩阵)后,你会得到一个均匀的4向量[x,y,z,w]。这称为npc(标准化投影坐标),也称为剪辑坐标。要获得屏幕上的二维坐标,通常使用

xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width

对于相机前面的点,这会提供您想要的。但是摄像机后面的几点会对你写得很好的回答表示感谢。这对我帮助很大。。。这是一个很好的答案,但有几件事我还不清楚。首先,您是否缺少行
wc=(n*w1)+(1-n)*w2)
?另外,投影矩阵P是否在右边相乘,即v_e*P?更重要的是,我使用的任何渲染器都不要求我在绘制时指定近平面-当不知道近平面值时,如何执行此剪裁?我可能已经初步找到了答案。显然,剪裁z时,约束w,因为它们是线性相关的。我遇到的问题是,如果你在插值w,你在插值测试z的剪辑值。事实上,方程并不像我想的那么难。对于由v_1和v_2给出的顶点v_3,其直线与剪裁平面相交,
w_3=w_1+r*(w_2-w_1)
a_3=a_1+r*(a_2-a_3)
,其中
a_n=dot(平面,v_n)
。但是a_3等于剪辑值w_3,所以
a_1+r*(a_2-a_1)=w_1+r*(w_2-w_1)
。求r,你就完成了。(我希望如此)。实现了上述功能后,我现在意识到这(当然)并不能解决-w问题,因为您被错误的剪裁平面剪裁了。然而,您不再需要将w带到近平面,只需要带到>=0,正如Qualia指出的,我没有定义wc。它等于near(因为这是与w=near的平面相交的点)。(我在答案中加了这个)。是的,投影(也称为剪辑)矩阵乘以其右侧的列主视点坐标:projection*Pview=Pnpc。另外,如果没有近平面,则实际上不可能进行投影,因此,如果渲染器没有要求您输入近值,那么它可能会为您选择一个近值。
xscreen = (x/w) * screen_width
yscreen = (y/w) * screen_width
[    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       ]
v1 = [x1, y1, z1, w1]
v2 = [x2, y2, z2, w2]
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]