透视分割后的Z值始终小于-1

时间:2010-07-15 13:18:26

标签: opengl 3d directx projection

所以我正在编写自己的自定义3D转换管道,以便更好地理解它是如何工作的。我可以正确地将所有内容渲染到屏幕上,现在我要回去查看裁剪。

根据我的理解,如果透视分割后的x或y值超出[-1,1]的范围,我应该剪切一个顶点,如果z值超出[0,1的界限],我应该剪裁一个顶点。 ,1]。

当我实现它时,我的z值始终为-1.xxxxxxxxxxx,其中xxxxxxx是一个非常小的数字。

这有点长,我道歉,但我想确保我提供了所有可能的信息。

第一个约定:

我正在使用左手系统,其中矩阵看起来像这样:

[m00, m01, m02, m03]
[m10, m11, m12, m13]
[m20, m21, m22, m23]
[m30, m31, m32, m33]

我的矢量是这样的列:

[x]
[y]
[z]
[w]

我的相机设置为:

以PI / 4为单位的垂直FOV。

1的宽高比:(方形视口)

近剪辑值为1。

远剪辑值为1000。

初始世界x位置为0。

初始世界y位置为0。

初始世界z位置为-500。

摄像机向下看Z轴(0,0,1)

给定一个顶点,管道的工作方式如下:

第1步:将顶点乘以相机矩阵。

第2步:将顶点乘以投影矩阵。

投影矩阵是:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

第3步:将x,y和z分量乘以1 / w。

第4步: [这就是问题所在]如果外边界,请剪切顶点。

第5步:转换为屏幕坐标。

我有一个示例顶点

(-100, -100, 0, 1)

乘以相机矩阵后,我得到:

(-100, -100, 500, 1)

这是有道理的,因为相对于相机,该顶点是左侧和下侧100个单位,前方500个单位。它也在1的近剪辑和1000的远剪辑之间.W仍然是1.

乘以投影矩阵后得到:

(-241.42135, -241.42135, 601.600600, -600.600600)

我不确定这是否有意义。 x和y看起来是正确的,但是我对于z和w感到不满,因为透视分割的下一步是奇数。

在透视划分后,我得到:

(0.401966, 0.401966, -1.001665, 1)

x和y再次有意义,它们都在[-1,1]的范围内。但是z值明显超出了界限,尽管我认为它仍然应该在最佳状态之内。 W又回到了1,这也是有道理的。

再次为小说道歉,但我希望有人可以帮助我弄清楚我做错了什么。

谢谢!

2 个答案:

答案 0 :(得分:3)

好吧,看起来我弄清楚它是什么问题。

我的投影矩阵是:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  1]
[0,       0,       -1.001001, 0]

但它确实应该转换成:

[2.41421, 0,       0,         0]
[0        2.41421, 0,         0]
[0,       0,       1.001001,  -1.001001]
[0,       0,       1,         0]

使用此矩阵时,我的x和y值保持与预期相同,现在我的z值被限制在[0,1]范围内,并且如果它们位于远剪裁平面附近,则仅超出该范围。 / p>

现在唯一的问题是,我很困惑我是使用右手还是左手系统。

我所知道的是现在它有效......

答案 1 :(得分:2)

我可能不在这里,但我认为投影矩阵和透视分界的目的是发现屏幕上该点的2D位置。在这种情况下,剩下的z值不一定具有任何意义,因为数学都是为了找到那两个x和y值。

更新: 我想我已经弄清楚了。你的数学都是正确的。您描述的相机和frustum在Z = 1处具有近剪裁平面,因此您在(-100,100,0)处的示例点实际上是剪裁平面的,因此z-buffer值略低于-1非常有意义。

尝试在平截头体内部使用z坐标的样本点,例如z坐标为2。