6

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

根据我的理解,如果透视分割后的 x 或 y 值超出 [-1, 1] 的范围,并且在我的情况下,如果 z 值超出 [0, 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。

-500 的初始世界 z 位置。

相机向下看位置 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,这又是有意义的。

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

谢谢!

4

2 回答 2

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] 范围内,并且只有在远裁剪平面的近端之外时才超出该范围。

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

我所知道的是,现在它可以工作了......

于 2010-07-16T14:57:08.963 回答
2

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

更新:我想我已经弄清楚了。你的数学是正确的。您描述的相机和平截头体在 Z = 1 处有一个近剪裁平面,因此您在 (-100, 100, 0) 处的示例点实际上位于剪裁平面之外,因此刚好低于 -1 的 z 缓冲区值非常完美感觉。

尝试在视锥体内使用 z 坐标的样本点,例如 z 坐标为 2。

于 2010-07-15T13:31:26.350 回答