从矩阵中获取视锥体的世界坐标



我有通常的立方体(-1,-1,-1到1,1,1(和我的相机矩阵(视图和投影(。 投影矩阵是透视投影。 我想看看从给定的相机可以看到哪个区域。为了想象这一点,我想像视锥体一样拉伸我的立方体,以便我可以看到来自其他相机的结果。

我的想法:

获取视图投影矩阵的倒数,并将单位立方体坐标与它相乘:

glm::vec4 CubeCoordinates[8]{                                        
glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f),
glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f), 
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 
glm::vec4(1.0f, -1.0f, 1.0f, 1.0f), 
glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f), 
glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f), 
glm::vec4(1.0f, 1.0f, -1.0f, 1.0f), 
glm::vec4(1.0f, -1.0f, -1.0f, 1.0f) };
glm::mat4 InvertedViewProjectionMatrix = glm::inverse(refCamera.GetViewProjectionMatrix());
for (uint32_t i = 0; i < 8; ++i)
{
CameraEdgesWorldSpace[i] = InvertedViewProjectionMatrix * CubeCoordinates[i];
}

现在立方体坐标应该在世界空间中,看起来像视锥体。 但是传出的坐标是错误的。

我可以保证,viewProjectionMatrix正常工作,因为我像在任何地方一样使用它。

计算有误吗? 还是我使用了错误的命令来反转矩阵(我是 GLM 的新手(?

投影矩阵将眼睛坐标映射到剪辑坐标。现在,您没有用于反向投影的剪辑坐标,只有 NDC 坐标。

如何从 NDC 转换为剪辑坐标?好吧,请记住,我们使用的是齐次坐标而不是欧几里得坐标(因此是第 4 维 w(。齐次坐标恰好在乘以非零常数方面是不变的。也就是说,对于任何非零k,点(a, b, c, d)等效于(k*a, k*b, k*c, k*d)

您可以通过将剪辑坐标乘以1/w来从剪辑坐标转到 NDC。这是一个乘以常数!因此,NDC 本身就是一个有效的剪辑坐标,因此您可以对其进行反向投影。

现在,从齐次坐标到欧几里得坐标总是需要除以w。我们通常不在OpenGL中这样做的原因是仿射变换不会影响w,所以它通常保持1。但在这种情况下并非如此,因为投影矩阵及其逆矩阵都会影响w坐标。

因此,正如BDL在评论中指出的那样,您缺少除法w。您需要在 NDC 坐标中获取可见立方体,通过一系列向后变换,最后除以w才能得到欧几里得坐标。事实上,您很可能会跳过除法w,因为您可能只是停留在均匀坐标中并使用另一台摄像机的视图进行渲染。

最新更新