opengl - 使用 glOrtho 时相机无法看到对象
opengl - camera cannot see object when glOrtho is used
我是 OpenGL 的新手,我正在尝试了解投影矩阵在其中的工作原理。
为了创建一个简单的案例,我在世界中定义了一个三角形space,它的坐标是:
(0,1,0), (1,0,0), (-1,0,0)
我将模型视图矩阵和投影矩阵设置如下:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
0, 0, 2,
0, 0, 0,
0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // does not work
// glOrtho(-2, 2, -2, 2, 0.1, 2.0); // works
根据我的理解,gluLookAt()
用于设置观察矩阵。由于OpenGL
并没有"camera"的概念,所以将整个世界进行了变换,达到了相机的效果。在上面的代码中,我假设 "camera" 位于 (0,0,2),查看 (0,0,0)。所以 OpenGL 在内部沿 z
轴将三角形向后移动到 z=-2
.
定义一个视锥体,glOrtho()
得到6个参数。为了使三角形在视锥体中可见,我将 near
和 far
值分别设置为 -0.1
和 -2.0
,这应该表明视锥体包括 [-0.1, -2.0]
在 z
轴上。
我搜索了类似的问题,发现有人说glOrtho()
的最后两个参数实际上是-near
和-far
。但是如果这是正确的,下面的代码应该可以工作(但它不会):
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
0, 0, -2, // changed 2 to -2, thus the triangle should be transformed to z=2?
0, 0, 0,
0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // -near=-0.1, -far=-2.0, thus the frustum should include [0.1, 2.0], thus include the triangle
如果我是对的,三角形应该画在屏幕上,所以我的代码一定有问题。有人可以帮忙吗?
首先请注意,固定功能管道矩阵堆栈和按 glBegin
/glEnd
序列绘制已弃用 10 多年。
阅读 Fixed Function Pipeline and see Vertex Specification 了解最先进的渲染方式。
如果你使用这样的视图矩阵:
gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);
然后在设置投影矩阵时,近平面和远平面的值必须为正值,
glOrtho(-2, 2, -2, 2, 0.1, 2.0);
因为,gluLookAt
将顶点转换为视图 space(在视图 space 中,z 轴指向视口外),但是投影矩阵反转了 z 轴。
但是要小心,因为三角形在 z=0
(0,1,0), (1,0,0), (-1,0,0)
并且从相机到三角形的距离为2,因为视图矩阵,三角形正好位于远平面上(也是2.0)。我建议将到远平面的距离从 2.0 增加到(例如)3.0:
glOrtho(-2, 2, -2, 2, 0.1, 3.0);
如果改变视图矩阵,
gluLookAt(0, 0, -2, 0, 0, 0, 0, 1, 0);
然后 (view space) z 轴仍然指向视口外,但是您看的是三角形的 "back" 侧。三角形仍在视图的中心 (0, 0, 0),但相机位置已更改。三角形还在镜头前。
如果你愿意
gluLookAt(0, 0, 2, 0, 0, 4, 0, 1, 0);
那么你的视线就会从三角形上移开。您必须将视图的背面投影到视口 "see" 三角形 (glOrtho(-2, 2, -2, 2, -0.1, -3.0);
)。
进一步注意,glOrtho
将当前矩阵乘以正交投影矩阵。这意味着您应该在使用 glOrtho
之前设置单位矩阵,就像您对模型视图矩阵所做的那样:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, 0.1, 2.0);
说明
投影、视图和模型矩阵一起交互以在视口上呈现场景的对象(网格)。
模型矩阵定义了场景世界space中单个对象(网格)的位置方向和比例。
视图矩阵定义了场景中观察者(观察者)的位置和观察方向。
投影矩阵定义了相对于投影到视口上的观察者(观察者)的区域(体积)。
在正交投影中,该区域(体积)由到观察者位置的 6 个距离(左、右、下、上、近、远)定义。
查看矩阵
视图坐标系描述了观察场景的方向和位置。视图矩阵从世界 space 转换为视图(眼睛)space。
如果视图space的坐标系是Right-handed系统,则X轴指向左侧,Y轴指向上方,Z轴指向视图外(请注意,在右手系统中,Z 轴是 X 轴和 Y 轴的叉积)。
投影矩阵
投影矩阵描述了从场景视图的 3D 点到视口上的 2D 点的映射。它从眼睛 space 变换到剪辑 space,并且剪辑 space 中的坐标通过除以剪辑坐标。 NDC 的范围为 (-1,-1,-1) 到 (1,1,1)。
超出剪辑 space 的每个几何图形都被剪辑。
在正交投影中,视图中的坐标 space 线性映射到剪辑 space 坐标,剪辑 space 坐标等于标准化设备坐标,因为 w
分量为1(对于笛卡尔输入坐标)。
left、right、bottom、top、near 和 far 的值定义了一个框。盒子体积内的所有几何体在视口上都是 "visible"。
正交投影矩阵如下所示:
r = right, l = left, b = bottom, t = top, n = near, f = far
2/(r-l) 0 0 0
0 2/(t-b) 0 0
0 0 -2/(f-n) 0
-(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
z轴被投影矩阵反转。
我是 OpenGL 的新手,我正在尝试了解投影矩阵在其中的工作原理。
为了创建一个简单的案例,我在世界中定义了一个三角形space,它的坐标是:
(0,1,0), (1,0,0), (-1,0,0)
我将模型视图矩阵和投影矩阵设置如下:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
0, 0, 2,
0, 0, 0,
0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // does not work
// glOrtho(-2, 2, -2, 2, 0.1, 2.0); // works
根据我的理解,gluLookAt()
用于设置观察矩阵。由于OpenGL
并没有"camera"的概念,所以将整个世界进行了变换,达到了相机的效果。在上面的代码中,我假设 "camera" 位于 (0,0,2),查看 (0,0,0)。所以 OpenGL 在内部沿 z
轴将三角形向后移动到 z=-2
.
定义一个视锥体,glOrtho()
得到6个参数。为了使三角形在视锥体中可见,我将 near
和 far
值分别设置为 -0.1
和 -2.0
,这应该表明视锥体包括 [-0.1, -2.0]
在 z
轴上。
我搜索了类似的问题,发现有人说glOrtho()
的最后两个参数实际上是-near
和-far
。但是如果这是正确的,下面的代码应该可以工作(但它不会):
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
0, 0, -2, // changed 2 to -2, thus the triangle should be transformed to z=2?
0, 0, 0,
0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // -near=-0.1, -far=-2.0, thus the frustum should include [0.1, 2.0], thus include the triangle
如果我是对的,三角形应该画在屏幕上,所以我的代码一定有问题。有人可以帮忙吗?
首先请注意,固定功能管道矩阵堆栈和按 glBegin
/glEnd
序列绘制已弃用 10 多年。
阅读 Fixed Function Pipeline and see Vertex Specification 了解最先进的渲染方式。
如果你使用这样的视图矩阵:
gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);
然后在设置投影矩阵时,近平面和远平面的值必须为正值,
glOrtho(-2, 2, -2, 2, 0.1, 2.0);
因为,gluLookAt
将顶点转换为视图 space(在视图 space 中,z 轴指向视口外),但是投影矩阵反转了 z 轴。
但是要小心,因为三角形在 z=0
(0,1,0), (1,0,0), (-1,0,0)
并且从相机到三角形的距离为2,因为视图矩阵,三角形正好位于远平面上(也是2.0)。我建议将到远平面的距离从 2.0 增加到(例如)3.0:
glOrtho(-2, 2, -2, 2, 0.1, 3.0);
如果改变视图矩阵,
gluLookAt(0, 0, -2, 0, 0, 0, 0, 1, 0);
然后 (view space) z 轴仍然指向视口外,但是您看的是三角形的 "back" 侧。三角形仍在视图的中心 (0, 0, 0),但相机位置已更改。三角形还在镜头前。
如果你愿意
gluLookAt(0, 0, 2, 0, 0, 4, 0, 1, 0);
那么你的视线就会从三角形上移开。您必须将视图的背面投影到视口 "see" 三角形 (glOrtho(-2, 2, -2, 2, -0.1, -3.0);
)。
进一步注意,glOrtho
将当前矩阵乘以正交投影矩阵。这意味着您应该在使用 glOrtho
之前设置单位矩阵,就像您对模型视图矩阵所做的那样:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, 0.1, 2.0);
说明
投影、视图和模型矩阵一起交互以在视口上呈现场景的对象(网格)。 模型矩阵定义了场景世界space中单个对象(网格)的位置方向和比例。 视图矩阵定义了场景中观察者(观察者)的位置和观察方向。 投影矩阵定义了相对于投影到视口上的观察者(观察者)的区域(体积)。
在正交投影中,该区域(体积)由到观察者位置的 6 个距离(左、右、下、上、近、远)定义。
查看矩阵
视图坐标系描述了观察场景的方向和位置。视图矩阵从世界 space 转换为视图(眼睛)space。
如果视图space的坐标系是Right-handed系统,则X轴指向左侧,Y轴指向上方,Z轴指向视图外(请注意,在右手系统中,Z 轴是 X 轴和 Y 轴的叉积)。
投影矩阵
投影矩阵描述了从场景视图的 3D 点到视口上的 2D 点的映射。它从眼睛 space 变换到剪辑 space,并且剪辑 space 中的坐标通过除以剪辑坐标。 NDC 的范围为 (-1,-1,-1) 到 (1,1,1)。
超出剪辑 space 的每个几何图形都被剪辑。
在正交投影中,视图中的坐标 space 线性映射到剪辑 space 坐标,剪辑 space 坐标等于标准化设备坐标,因为 w
分量为1(对于笛卡尔输入坐标)。
left、right、bottom、top、near 和 far 的值定义了一个框。盒子体积内的所有几何体在视口上都是 "visible"。
正交投影矩阵如下所示:
r = right, l = left, b = bottom, t = top, n = near, f = far
2/(r-l) 0 0 0
0 2/(t-b) 0 0
0 0 -2/(f-n) 0
-(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
z轴被投影矩阵反转。