从透视切换到正交保持模型的相同视图大小和缩放

Nik*_*ond 7 c++ opengl orthographic perspectivecamera glm-math

我有fov角度 = 60,width= 640 和height= 480 的窗口,near= 0.01 和far= 100 平面,我使用投影矩阵glm::perspective()

glm::perspective(glm::radians(fov),
                              width / height,
                              zNear,
                              zFar);
Run Code Online (Sandbox Code Playgroud)

它运作良好。

然后我想将投影类型更改为正交,但我不知道如何glm::ortho()正确计算输入参数。我尝试了很多方法,但问题是切换到模型对象的正交投影大小后成为另一个。

让我有一个中心在 (0.5, 0.5, 0.5) 和长度大小为 1 的立方体,以及带有 mEye 的相机 (0.5, 0.5, 3),mTarget 在 (0.5, 0.5, 0.5) 和 mUp (0, 1, 0) )。视图矩阵glm::lookAt(mEye, mTarget, mUp) 使用透视投影效果很好。随着glm::ortho(-width, width, -height, height, zNear, zFar)我的立方体成为窗口的中央小的像素。我也试过实现这个变体如何在保持所需对象大小的透视和正交相机之间切换, 但结果(几乎)与以前相同。

那么,第一个问题是如何计算正交参数以保存对象的原始视图大小/相机的位置?

此外,缩放

auto distance = glm::length(mTarget - mEye)
mEye = mTarget - glm::normalize(mTarget - mEye) * distance;
Run Code Online (Sandbox Code Playgroud)

对正射没有影响。因此第二个问题是如何在正交投影的情况下实现缩放?

Ps 我假设我理解正确。模型的比例不取决于深度,但我仍然可以决定相机在哪里正确设置模型大小并使用缩放。此外,我认为这是一项简单而微不足道的任务,例如,在开发 3D 查看器/编辑器/等时。如果不是,请纠正我。

Rab*_*d76 7

如何计算正交参数以保存物体的原始视图尺寸/相机位置?

在正交投影中,3 维场景平行投影到 2 维视口。
这意味着投影在视口上的对象始终具有相同的大小,与其深度(到相机的距离)无关。

透视投影描述了从针孔相机看到的世界上的 3D 点到视口的 2D 点的映射。
这意味着投影在视口上的对象因其深度而变小。

如果将透视切换为正交投影,则仅显示 1 个平面中的对象,该平面与 viepwort 平面(平行),并保持其深度。请注意,平面是二维的并且没有“深度”。这导致当投影切换时,3 维对象永远不会“看起来”相同。但二维广告牌可以保持其尺寸。

透视投影的深度与尺寸之比是线性的并且可以计算。它仅取决于视角:

float ratio_size_per_depth = atan(glm::radians(fov / 2.0f) * 2.0f;
Run Code Online (Sandbox Code Playgroud)

如果您想设置正交投影,将尺寸保持在一定距离(深度),那么您必须首先定义深度:

例如到目标点的距离:

auto distance = glm::length(mTarget - mEye);
Run Code Online (Sandbox Code Playgroud)

投影可以这样设置:

float aspect = width / height
float size_y = ratio_size_per_depth * distance;
float size_x = ratio_size_per_depth * distance * aspect;

glm::mat4 orthProject = glm::ortho(-size_x, size_x, -size_y, size_y, 0.0f, 2.0f*distance);
Run Code Online (Sandbox Code Playgroud)

如何在正射投影的情况下实现缩放?

缩放正交投影的 XY 分量:

float aspect = width / height
float size_y = ratio_size_per_depth * distance;
float size_x = ratio_size_per_depth * distance * aspect;

glm::mat4 orthProject = glm::ortho(-size_x, size_x, -size_y, size_y, 0.0f, 2.0f*distance);
Run Code Online (Sandbox Code Playgroud)

设置> 1.0的值orthScale表示放大,设置一个< 1.0 的值表示缩小。