使用OpenGL进行透视投影

时间:2012-02-26 22:59:38

标签: opengl projection perspective

我对透视投影感到困惑。

这种情况令我感到困惑。我的frustrum的前平面基本上位于正z轴,背平面位于负轴,并沿着正z轴旋转大约几度。

现在,每当我通过示例时,我都会看到近平面和远平面都存在于负z轴上。

我在这种情况下的做法基本上是这样的:

glMatrixMode(GL_PROJECTION);    
glLoadIdentity();
glFrustrum(-xval,+xval,-yval,+yval,-10,+10);
gluLookAt(); // some point lying on this axis of symmetry about the point
glMatrixMode(GL_MODELVIEW);

所以,在上面的例子中,对于z具有负值和正值的glFrustum,我应该期待什么行为。即在这种情况下-10到+10。

3 个答案:

答案 0 :(得分:7)

视图卷定义了您实际看到的世界的数量,每个对象在外面视图体积不可见,并且内部的所有内容都可能是可见的(如果没有被遮挡)通过它前面的一个物体)。

视图体积的形状由您使用的投影类型决定。

投影和透视投影有两种类型。

Ortographic不考虑观察者的距离(不自然但对CAD软件等有用)和透视投影,它们将观察者的距离考虑在内,因此更远的物体看起来更小。

ortographic 投影中,视图体积是一个立方体,在透视投影中,视图体积的形状为平截头体(近剪裁平面小于远剪裁平面)。

在任何一种情况下,视图体积的内容都“投射”到近剪裁平面上。

当然,这个过程比简单的projection_matrix乘法与视图体积中的每个顶点相关得多;但它几乎在每本OpenGL相关书籍中都有解释。

查看体积形状在某种程度上模拟了相机属性...您看到的距离,您看到的距离等等。

red book在专门的观察​​章节中解释了这一点。

当谈到视锥体时,你暗示你正在使用透视投影。

要构造平截头体,您需要8个点,并且您通常希望构建一个对称的平截头体,这简化了投影矩阵。

不是直接手动指定8个点,而是使用辅助方法 gluPerspective(fovy,aspect_ratio,near,far),它使用“更直观”的参数进行视锥体构造;它基本上是glFrustum的包装器,为你计算8个点,然后调用glFrustum代替你。

对于OpenGL 3.0及更高版本,您将提供自己的gluPerspective实现,您只需谷歌代码即可。

记住投影让3D成为2D。

关于观看,OpenGL使用右手坐标系(x轴指向左,y轴指向上,z轴指向屏幕外。); DirectX使用左手坐标系。

请记住,在3​​D空间中,您只有2个坐标系方向(左手和右手)。

区别在于z轴的方向;如果你使z轴向内指向它是一个左手系统,或者如果你向外指向z指向它是一个右手系统。

z轴的任何其他方向都不会使z轴垂直于x和y轴,因此您将没有坐标系。

手性决定了正旋转发生在哪个方向等等。

您的相机位于原点(0,0,0),默认情况下朝下-z轴;在你不进行某种转变之前,它会是那样的。

您的视锥体是围绕观察方向构建的,而近视剪裁平面位于z = -near,距离最初位于原点的相机。

当您指定 作为glFrustum的正值时,您尚未指定其 z 位置平面位于 z = -near ,因为摄像机沿负z轴的默认方向,并且因为摄像机最初位于原点(0,0,0)并且您的近剪裁平面是始终靠近远离观众的眼睛位置,即相机位置。

每当您更改视图(更改摄像机位置或更改摄像机方向或两者)时,您的视锥体仍将“围绕新视图方向”并且近剪裁平面仍将“靠近”远离新摄像机位置

希望你能得到这个概念。

Frustum定义了多少。

无论相机站在哪里并指向。

答案 1 :(得分:4)

  

所以,在上面的例子中,对于z具有负值和正值的glFrustum,我应该期待什么行为。即在这种情况下-10到+10。

破碎。你应该期望这种行为被打破。

The documentation对此很清楚:

  

nearVal farVal :指定到近深度和远深度剪裁平面的距离。 两个距离必须为正。

(强调补充)

为这些值传递负数(或零)将产生不良。

答案 2 :(得分:2)

  

现在,每当我通过示例时,我都会看到近距离和远距离平面都存在于-ive z轴上。

当然。否则你会得到类似这样的东西

enter image description here

所有投影都相对于原点0发生。近和远确定剪裁平面与原点的距离。左右限定了平截头体与近平面的开口角度。如果在原点的相反方向放置“近”和远平面,则投影空间的形状就像沙漏。

glMatrixMode(GL_PROJECTION);    
glLoadIdentity();
glFrustrum(-xval,+xval,-yval,+yval,-10,+10);
gluLookAt(); // some point lying on this axis of symmetry about the point
glMatrixMode(GL_MODELVIEW);

投影并不意味着放置视图。投影是虚拟相机的“镜头”。您可以将其用于tilt and shift your lens并设置“焦距”。但它并不意味着“放置你的相机”。这应该通过模型 view 矩阵发生。

  

所以,在上面的例子中,对于z具有负值和正值的glFrustum,我应该期待什么行为。即在这种情况下-10到+10。

从远处到“近”平面,当物体接近0时,物体将变大,因为Z = 0它们处于奇点并且无限地爆炸,然后越来越接近它们将变小但将会变小反转,即围绕Z轴旋转180°,深度值转向,即通过深度测试深度排序将拒绝接近0到0附近的碎片。