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

时间:2019-03-04 16:30:00

标签: c++ opengl glm-math

我有fov角度= 6​​0,宽度= 640和高度= 480的窗口,near = 0.01和far = 100个平面,我使用glm::perspective()得到投影矩阵

glm::perspective(glm::radians(fov),
                              width / height,
                              zNear,
                              zFar);

效果很好。

然后,我想将投影类型更改为正交,但是我不知道如何正确计算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),我的立方体变成了窗口中心的一个小像素。 我也尝试实现此变体How to switch between Perspective and Orthographic cameras keeping size of desired object 但结果(几乎)与以前相同。

所以,第一个问题是如何计算正交参数以保存摄像机的物体/位置的原始视图大小?

此外,使用

进行缩放
auto distance = glm::length(mTarget - mEye)
mEye = mTarget - glm::normalize(mTarget - mEye) * distance;

对邻位无效。 第二个问题是在正交投影的情况下如何实现缩放?

P.s。 我假设我正确理解了邻位。模型的比例并不取决于深度,但是尽管如此,我仍然可以决定相机在哪里以正确设置模型大小并使用缩放。我还假设这是一个简单而琐碎的任务,例如,在开发3D查看器/编辑器/等时。如果不是,请纠正我。

1 个答案:

答案 0 :(得分:2)

  

如何计算正交参数以保存摄像机的对象/位置的原始视图大小?

在正交投影中,三维场景是与二维视口平行的投影。
这意味着投影在视口上的对象始终具有相同的大小,而与它们的深度(与摄影机的距离)无关。

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

如果将形式透视图切换为正交投影,则仅将1个平面内的对象(垂直于viepwort平面)平行于viepwort,深度为kkp。注意,平面是二维的,没有“深度”。这导致在切换投影时,二维对象永远无法“看起来”相同。但是二维广告牌可以保持其他尺寸。

透视投影处的深度与大小的比率是线性的,可以计算。它仅取决于视野视角:

float ratio_size_per_depth = atan(glm::radians(fov / 2.0f) * 2.0f;

如果要设置正交投影,以将尺寸保持一定距离(深度),则必须先定义深度:

例如到目标点的距离:

auto distance = glm::length(mTarget - mEye);

投影可以这样设置:

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

glm::mat4 orthProject = glm::ortho( -size_x, size_x, -size_y, size_y, 0.0f, 2.0f*distance );

  

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

缩放正交投影的XY分量:

glm::mat4 orthProject = glm::ortho( -size_x, size_x, -size_y, size_y, 0.0f, 2.0f*distance );

float orthScale = 2.0f;
orthProject = glm::scale(orthProject, glm::vec3(orthScale, orthScale, 1.0f));

orthScale设置一个值为> 1.0 的值以进行放大,为一个 <1.0 的值以进行缩小。