透视除法后的 Z 值始终小于 -1
因此,我正在编写自己的自定义 3D 转换管道,以便更好地了解其工作原理。我可以将所有内容正确渲染到屏幕上,现在我要返回并查看剪辑。
根据我的理解,如果透视分割后的 x 或 y 值超出 [-1, 1] 的范围,并且在我的情况下,如果 z 值超出 [0, 1] 的范围,我应该裁剪顶点。
然而,当我实现该方法时,我的 z 值始终为 -1.xxxxxxxxxx,其中 xxxxxxx 是一个非常小的数字。
这有点长,我很抱歉,但我想确保我提供了所有我能提供的信息。
第一个约定:
我使用的是左手系统,其中矩阵如下所示:
[m00, m01, m02, m03]
[m10, m11, m12, m13]
[m20, m21, m22, m23]
[m30, m31, m32, m33]
我的向量是如下所示的列:
[x]
[y]
[z]
[w]
我的相机设置为:
A垂直 FOV(以 PI/4 弧度表示)。
长宽比为 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,这又有意义了。
再次为这本小说道歉,但我希望有人能帮助我找出我做错了什么。
谢谢!
So I'm writing my own custom 3D transformation pipeline in order to gain a better understanding of how it all works. I can get everything rendering to the screen properly and I'm now about to go back and look at clipping.
From my understanding, I should be clipping a vertex point if the x or y value after the perspective divide is outside the bounds of [-1, 1] and in my case if the z value is outside the bounds of [0, 1].
When i implement that however, my z value is always -1.xxxxxxxxxxx where xxxxxxx is a very small number.
This is a bit long, and I apologize, but I wanted to make sure I gave all the information I could.
First conventions:
I'm using a left-handed system where a Matrix looks like this:
[m00, m01, m02, m03]
[m10, m11, m12, m13]
[m20, m21, m22, m23]
[m30, m31, m32, m33]
And my vectors are columns looking like this:
[x]
[y]
[z]
[w]
My camera is set up with:
A vertical FOV in radians of PI/4.
An aspect ration of 1. (Square view port)
A near clip value of 1.
A far clip value of 1000.
An initial world x position of 0.
An initial world y position of 0.
An initial world z position of -500.
The camera is looking down the position Z axis (0, 0, 1)
Given a vertex, the pipeline works like this:
Step 1: Multiply the vertex by the camera matrix.
Step 2: Multiply the vertex by the projection matrix.
Projection matrix is:
[2.41421, 0, 0, 0]
[0 2.41421, 0, 0]
[0, 0, 1.001001, 1]
[0, 0, -1.001001, 0]
Step 3: Multiply the x, y and z components by 1/w.
Step 4: [This is where the problem is] Clip the vertex if outside bounds.
Step 5: Convert to screen coordinates.
An example vertex that I have is
(-100, -100, 0, 1)
After multiplying by the camera matrix i get:
(-100, -100, 500, 1)
Which makes sense because relative to the camera, that vertex is 100 units to the left and down and 500 units ahead. It is also between the near clip of 1 and the far clip of 1000. W is still 1.
After multiplying by the projection matrix i get:
(-241.42135, -241.42135, 601.600600, -600.600600)
This I'm not sure if it makes sense. The x and y seem to be correct, but i'm iffy about the z and w since the next step of perspective divide is odd.
After the perspective divide I get:
(0.401966, 0.401966, -1.001665, 1)
Again the x and y make sense, they are both within the bounds of [-1, 1]. But the z value is clearly outside the bounds even though i believe it should still be within the frustrum. W is back to 1 which again makes sense.
Again apologies for the novel, but I'm hoping someone can help me figure out what I'm doing incorrectly.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,看来我知道问题出在哪里了。
我的投影矩阵是:
但它确实应该转置为:
使用此矩阵时,我的 x 和 y 值与预期保持相同,现在我的 z 值被限制在 [0, 1] 内,并且只有在以下情况下才超出该范围它们位于近剪裁平面或远剪裁平面之外。
现在唯一的问题是我很困惑我使用的是右手还是左手系统。
我所知道的是现在它可以工作了......
Ok, it looks like I figured out what the problem it was.
My projection matrix was:
But it really should be transposed and be:
When using this matrix, my x and y values stay the same as expected and now my z values are constrained to be within [0, 1] and only exceed that range if they are outside the near of far clip plane.
The only issue now is that I'm quite confused as to whether I'm using a right or left handed system.
All i know is that now it works...
我可能不适合这里,但我认为投影矩阵和透视划分的目的是发现屏幕上该点的 2D 位置。在这种情况下,剩下的 z 值不一定再有任何意义,因为数学都是为了找到这两个 x 和 y 值。
更新:我想我已经弄清楚了。你的数学全部正确。您描述的相机和 平截头体 在 Z=1 处有一个近剪裁平面,因此您的示例点(-100, 100, 0) 处实际上位于裁剪平面的外部,因此 z 缓冲区值略低于 -1 是完全合理的。
尝试使用 z 坐标位于平截头体内的采样点,例如 z 坐标为 2。
I may be out of my league here, but I thought that the purpose of the projection matrix and perspective divide were to discover the 2D position of that point on the screen. In that case, the left-over z value would not necessarily have any meaning any more, since the math is all geared towards finding those two x and y values.
Update: I think I have it figured out. Your math is all correct. The camera and frustum you describe has a near clipping plane at Z=1, so your example point at (-100, 100, 0) is actually outside of the clipping plane, so that z-buffer value of just below -1 makes perfect sense.
Try a sample point with a z-coordinate inside your frustum, say with a z-coordinate of 2.