我有fov角度= 60,宽度= 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查看器/编辑器/等时。如果不是,请纠正我。
答案 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 的值以进行缩小。