关于视图矩阵和视锥剔除
About view matrix and frustum culling
我试图确定一个对象(球体)是否在视锥体内。我的策略是先获取视图矩阵:
glm::lookAt(cameraPosition, lookAtPosition, cameraUp);
其中 cameraPosition
是相机的位置,lookAtPosition
是由 cameraPosition + cameraDirection
计算的, cameraUp
是不言自明的。
获得视图矩阵后,我计算了camera view中平截头体的8个顶点,然后将视图矩阵的逆乘以每个点得到它们在世界中的坐标space。
使用世界上的这 8 个点 space,我可以通过叉积构造 6 个平面(因此它们的法线将指向内部)。然后我将对象向量的点积(我通过用该平面上的任意点减去对象位置得到向量)与每个平面的法向量,如果它对所有 6 个都是正的,我知道它在平截头体内部.
所以我的问题是:
- 相机视角是否始终设置在 (0,0,0) 并注视正 z 方向?
- 视图矩阵将世界视图转换为相机视图,如果我使用它的逆矩阵将相机视图转换为世界视图,是否正确?
我的截锥体与我的 cameraDirection
相反,这导致屏幕上看不到任何东西(但它仍然在我的相机后面画东西)。
Is the camera view is always set at (0,0,0) and looking at the positive z direction?
视图 space 是定义场景外观的 space。
哪一部分被“看到”(投影到视口上)取决于投影矩阵。通常(在 OpenGL 中)原点是 (0,0,0) 并且视图 space z 轴指向视口之外。但是,投影矩阵反转 z 轴。它从视图 space 的 Right-handed 系统变为标准化设备 space 的左手系统。
the inverse of it to transform the camera view to the world view
是的。
视图矩阵从世界 space 转换为视图 space。投影矩阵变换 Cartesian coordinates of the view space to the Homogeneous coordinates of the clipspace. Clipspace coordinates are transformed to normalized device space by dividing the xyz components by the w component (Perspective divide).
归一化设备space是一个立方体,最小值为(-1, -1, -1),最大值为(1, 1, 1)。所以立方体的 8 个角点是归一化设备中可视体积的角 space.
(-1, -1, -1) ( 1, -1, -1) ( 1, 1, -1) (-1, 1, -1) // near plane
(-1, -1, 1) ( 1, -1, 1) ( 1, 1, 1) (-1, 1, 1) // far plane
如果您想将一个点从标准化设备 space 转换为视图 space,您必须:
- 通过逆投影矩阵变换
- 通过逆视图矩阵变换
- 将结果的 xyz 分量除以其 w 分量
glm::mat4 view; // view matrix
glm::mat4 projetion; // projection matrix
glm::vec3 p_ndc; // a point in normalized device space
glm::mat4 inv_projetion = glm::inverse( projetion );
glm::mat4 inv_view = glm::inverse( view );
glm::vec4 pth = inv_view * inv_projetion * glm::vec4( p_ndc, 1.0f );
glm::vec3 pt_world = glm::vec3( pth ) / pth.w;
我试图确定一个对象(球体)是否在视锥体内。我的策略是先获取视图矩阵:
glm::lookAt(cameraPosition, lookAtPosition, cameraUp);
其中 cameraPosition
是相机的位置,lookAtPosition
是由 cameraPosition + cameraDirection
计算的, cameraUp
是不言自明的。
获得视图矩阵后,我计算了camera view中平截头体的8个顶点,然后将视图矩阵的逆乘以每个点得到它们在世界中的坐标space。
使用世界上的这 8 个点 space,我可以通过叉积构造 6 个平面(因此它们的法线将指向内部)。然后我将对象向量的点积(我通过用该平面上的任意点减去对象位置得到向量)与每个平面的法向量,如果它对所有 6 个都是正的,我知道它在平截头体内部.
所以我的问题是:
- 相机视角是否始终设置在 (0,0,0) 并注视正 z 方向?
- 视图矩阵将世界视图转换为相机视图,如果我使用它的逆矩阵将相机视图转换为世界视图,是否正确?
我的截锥体与我的 cameraDirection
相反,这导致屏幕上看不到任何东西(但它仍然在我的相机后面画东西)。
Is the camera view is always set at (0,0,0) and looking at the positive z direction?
视图 space 是定义场景外观的 space。
哪一部分被“看到”(投影到视口上)取决于投影矩阵。通常(在 OpenGL 中)原点是 (0,0,0) 并且视图 space z 轴指向视口之外。但是,投影矩阵反转 z 轴。它从视图 space 的 Right-handed 系统变为标准化设备 space 的左手系统。
the inverse of it to transform the camera view to the world view
是的。
视图矩阵从世界 space 转换为视图 space。投影矩阵变换 Cartesian coordinates of the view space to the Homogeneous coordinates of the clipspace. Clipspace coordinates are transformed to normalized device space by dividing the xyz components by the w component (Perspective divide).
归一化设备space是一个立方体,最小值为(-1, -1, -1),最大值为(1, 1, 1)。所以立方体的 8 个角点是归一化设备中可视体积的角 space.
(-1, -1, -1) ( 1, -1, -1) ( 1, 1, -1) (-1, 1, -1) // near plane
(-1, -1, 1) ( 1, -1, 1) ( 1, 1, 1) (-1, 1, 1) // far plane
如果您想将一个点从标准化设备 space 转换为视图 space,您必须:
- 通过逆投影矩阵变换
- 通过逆视图矩阵变换
- 将结果的 xyz 分量除以其 w 分量
glm::mat4 view; // view matrix
glm::mat4 projetion; // projection matrix
glm::vec3 p_ndc; // a point in normalized device space
glm::mat4 inv_projetion = glm::inverse( projetion );
glm::mat4 inv_view = glm::inverse( view );
glm::vec4 pth = inv_view * inv_projetion * glm::vec4( p_ndc, 1.0f );
glm::vec3 pt_world = glm::vec3( pth ) / pth.w;