我有一个关于标准透视投影矩阵的问题,这是从
我认为,在使用透视矩阵转换点之后,位于近裁剪平面上的对象将映射到Z值为-1,而靠近远裁剪平面的对象将映射到Z值为1。
例如,假设您有一个位于原点处,朝向正Z轴方向的相机,近裁剪平面设置为1.0,远裁剪平面设置为2.0。然后,我会期望在“世界”Z坐标介于1.0和2.0之间的物体被转换为具有投影坐标-1.0和1.0之间的坐标。
换句话说,我期望以下C++代码:
但是它并没有打印出来这个:
我不明白为什么会这样。近裁剪平面的投影效果如我所预期,但是在两个平面之间正中间的一个点在投影时更靠近后面,而远裁剪平面上的一个点则完全超出了[-1,1]的范围。
我猜测可能有一些基本的数学知识我没有掌握,所以我向你们请教。
(顺便说一下,我正在处理的实际上是用Rust编写的,而不是C++,但是我切换到C++进行测试,以确保Rust实现中没有错误或其他问题。)
gluPerspective()
或glm::perspective()
获得的。具体来说,我想了解近/远裁剪平面的工作原理。我认为,在使用透视矩阵转换点之后,位于近裁剪平面上的对象将映射到Z值为-1,而靠近远裁剪平面的对象将映射到Z值为1。
例如,假设您有一个位于原点处,朝向正Z轴方向的相机,近裁剪平面设置为1.0,远裁剪平面设置为2.0。然后,我会期望在“世界”Z坐标介于1.0和2.0之间的物体被转换为具有投影坐标-1.0和1.0之间的坐标。
换句话说,我期望以下C++代码:
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
void print_vec(vec4 pnt) {
std::cout << "(" << pnt.x << ", " << pnt.y << ", " << pnt.z << ")" << "\n";
}
int main() {
mat4x4 view = lookAt(
vec3(0.0f, 0.0f, 0.0f), // eye at origin
vec3(0.0f, 0.0f, 1.0f), // looking towards +Z
vec3(0.0f, 1.0f, 0.0f)); // up is +Y
mat4x4 projection = perspective(
radians(90.0f), // field of view
1.0f, // aspect ratio
1.0f, // near clipping plane
2.0f); // far clipping plane
// transformation matrix for world coordinates
mat4x4 vp = projection * view;
// points (0,0,1), (0,0,1.5) and (0,0,2) in homogeneous coordinates
print_vec(vp * vec4(0.0f, 0.0f, 1.0f, 1.0f));
print_vec(vp * vec4(0.0f, 0.0f, 1.5f, 1.0f));
print_vec(vp * vec4(0.0f, 0.0f, 2.0f, 1.0f));
}
打印这个
(0, 0, -1)
(0, 0, 0)
(0, 0, 1)
但是它并没有打印出来这个:
(0, 0, -1)
(0, 0, 0.5)
(0, 0, 2)
我不明白为什么会这样。近裁剪平面的投影效果如我所预期,但是在两个平面之间正中间的一个点在投影时更靠近后面,而远裁剪平面上的一个点则完全超出了[-1,1]的范围。
我猜测可能有一些基本的数学知识我没有掌握,所以我向你们请教。
(顺便说一下,我正在处理的实际上是用Rust编写的,而不是C++,但是我切换到C++进行测试,以确保Rust实现中没有错误或其他问题。)