我在 Vulkan 中有一个 3D 应用程序,其中正在渲染一个简单的 3D 模型。通常,我使用 glm 的透视投影,如下所示:
// Vulkan-trick because GLM was written for OpenGL, and Vulkan uses
// a right-handed coordinate system instead. Without this correction,
// geometry will be y-inverted in screen space, and the coordinate space
// will be left-handed. Described at:
// https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
glm::mat4 correction(
glm::vec4(1.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, -1.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.5f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.5f, 1.0f));
camera->projectionMatrix = correction * glm::perspectiveFov(fov, w, h, near, far);
这个效果很好。
所以,现在尝试使用正交投影:
float aspect = h / w; // window height/width in pixels
camera->projectionMatrix = correction * glm::ortho(-1.0f, 1.0f, -aspect, aspect, near, far);
3D 模型仍然会渲染,尽管它比以前更大,所以我可能在创建正交投影矩阵时犯了错误。
但问题是相机现在无法在场景中向前/向后移动,这在透视投影中效果很好。底层设置如下所示:
// called every frame if up arrow key is pressed
void camera_move_forward(Camera* camera, float distance)
{
camera->position += camera->front * distance;
}
// called every frame
static void update(Camera* camera)
{
const glm::quat& q = camera->orientation;
camera->viewMatrix = glm::translate(glm::mat4_cast(q), camera->position);
camera->front = glm::rotate(glm::conjugate(q), glm::vec3(0.0f, 0.0f, 1.0f));
camera->up = glm::rotate(glm::conjugate(q), glm::vec3(0.0f, 1.0f, 0.0f));
camera->right = glm::normalize(glm::cross(-camera->up, camera->front));
}
可观察到的行为是
camera_move_forward
不会改变屏幕上 3D 对象的大小。但是,如果我长时间按住向上/向下箭头键,我可以看到近/远平面工作正常,因为模型开始“剪切”。
这通常是如何完成的?我以前没有使用过正交投影。
这篇帖子提供了一个很好的答案。简而言之,它正在按设计工作。 3D 场景以平行方式投影到 2D,因此移动相机位置不会改变对象的大小,因为对象的范围始终看起来相距相同的距离。因此,“并行”。为了“放大”或缩小对象,您必须更改正交范围或以其他方式修改变换堆栈。