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

w80xi6nr  于 2023-04-20  发布在  其他
关注(0)|答案(2)|浏览(142)

我有fovAngular = 60,width = 640和height = 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),m目标(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.我假设我正确地理解了ortho。模型的比例不依赖于深度,但尽管如此,我仍然可以决定相机在哪里,以正确地设置模型的大小和使用缩放。此外,我假设这是简单而琐碎的任务,例如,当开发3D查看器/编辑器/等时。如果不是,请纠正我。

p5cysglq

p5cysglq1#

如何计算正交参数以保存物体原始视图尺寸/摄像机位置?
在正交投影中,三维场景平行投影到二维视口。
这意味着投影在视口上的对象始终具有相同的大小,而与其深度(到摄影机的距离)无关。
透视投影描述了从世界中的3D点到视口的2D点的Map,如从针孔相机看到的。
这意味着投影到视口上的对象会变小,缩小的程度与其深度相同。
如果您从透视切换到正交投影,则只有1个平面中的对象,该平面与viepwort平面(平行),并保持其深度。请注意,平面是2维的,没有“深度”。这导致3维对象永远不会“看起来”相同,当投影切换时。但是2维广告牌可以保持其大小。
透视投影的深度与尺寸的比值是线性的,可以计算。它仅取决于视场角:

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 * 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);

在正投影情况下如何实现缩放?
缩放正交投影的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 以用于缩小。

gdrx4gfi

gdrx4gfi2#

声明:
float ratio_size_per_depth = atan(glm::radians(fov / 2.0f)* 2.0f;
半正确解:
(1)float ratio_size_per_depth = atan(glm::radians(fov / 2.0f))* 2.0f;
更好(更准确)的解决方案:
float ratio_size_per_depth = glm::radians(fov);
此外:
glm::mat4 orthProject = glm::ortho(-size_x,size_x,-size_y,size_y,0.0f,2.0f*distance);
应该是
glm::mat 4 orthProject = glm::ortho(-size_x,size_x,-size_y,size_y,-2.0f * 距离,2.0f * 距离);

相关问题