透视投影

来源:互联网 发布:记事本是什么软件 编辑:程序博客网 时间:2024/04/28 03:49

透视投影最显著的特征就是透视缩短,物体距离照相机越远,它在最终图像中看上去就越小。这是因为透视投影的视景体可以看成是一个金字塔的平截头体(顶部被一个平行于底面的平面截除)。位于视景体之内的物体被投影到金字塔的顶点,也就是照相机或观察点的位置。靠近观察点的物体看上去更大一些,因为和远处的物体相比,它们占据了视景体中相对较大的区域。这种投影方法常用于动画、视觉模拟以及其他要求某种程度的现实感的应用领域,因为它和我们在日常生活中观察事物的方式相同。

glFrustum()函数定义了一个平截头体,它计算一个用于实现透视投影的矩阵,并把它与当前的投影矩阵(一般为单位矩阵)相乘。记住,视景体用于裁剪那些位于它之外的物体。平截头体的4个侧面、顶面和底面对应于视景体的6个裁剪平面,如图3-13所示。位于这些平面之外的物体(或物体的一部分)将裁剪掉, 不会出现在最终的图像中。注意glFrustum()函数并不需要定义一个对称的视景体。

 图3-13 glFrustum()函数所指定的透视视景体


  1. void glFrustum(GLdouble left, GLdouble right,  
  2. GLdouble bottom, GLdouble top,  
  3. GLdouble near, GLdouble far); 

创建一个表示透视视图平截头体的矩阵,并把它与当前矩阵相乘。平截头体的视景体是由这个函数的参数定义的:(left, bottom, -near)和(right, top, -near)分别指定了近侧裁剪平面左上角和右下角的(x, y, z)坐标。near和far分别表示从观察点到近侧和远侧裁剪平面的距离,它们的值都应该是正的。

平截头体在三维空间中有一个默认的方向。可以在投影矩阵上执行旋转或移动,对这个方向进行修改。但是,这种做法难度较大,因此最好还是避免。

高级话题

平截头体并不一定要求是对称的, 它的轴也并不需要与z 轴对齐。例如, 可以使用glFrustum()函数绘制一幅图片,就像透过房子右上角的一个矩阵窗口向外观察一样。摄像师使用这种视景体创建人工透视效果。通过这种方法,可以让硬件按照两倍于常规的分辨率计算图像,供打印机使用。例如,如果想让一幅图像的分辨率两倍于屏幕的分辨率,可以分4次绘制同一幅图像,每次使用平截头体用四分之一的图像覆盖整个屏幕。在图像的每个四分之一均被渲染之后,就可以读取像素,以收集高分辨率图像的数据(关于读取像素数据的更多信息,请参阅第8章)。

尽管在概念上理解起来非常轻松,但是glFrustum()函数用起来并不是非常直观。因此,可以试用OpenGL工具函数库的gluPerspective()函数。这个函数创建一个视景体,它与调用glFrustum()产生的视景体相同,可以用一种不同的方式来指定它。这个函数并不是指定近侧裁剪平面的两个角,而是指定y方向上视野的角度(见图3-14)和纵横比(x/y)。对于正方形的屏幕,纵横比为1.0。这两个参数足以确定沿视线方向的平截头体金字塔,如图3-14所示。还需要指定观察点和近侧以及远侧裁剪平面的距离,也就是对这个金字塔进行截除。注意,gluPerspective()仅限于创建沿视线方向同时对称于x轴和y轴的平截头体,但是我们通常所需要的就是这种平截头体。

 图3-14 由gluPerspective()所指定的透视视景体

和glFrustum()函数一样,可以执行旋转或移动,改变gluPerspective()创建的视景体的默认方向。如果不执行这样的变换,观察点就位于原点,视线的方向是沿z轴的负方向。

使用gluPerspective()时,需要挑选正确的视野值,否则图像看上去就会变形。为了获得完美的视野,可以推测自己的眼睛在正常情况下距离屏幕有多远以及窗口有多大,并根据距离和大小计算视野的角度。计算结果可能比自己想象的要小。我们也可以换一种方法考虑这个问题。一个35mm的照相机如果要达到94度的视野,它的镜头就要求达到20mm,这已经是非常宽的镜头了(关于如何计算视野的详细信息,请参阅第3.5节)。


  1. void gluPerspective(GLdouble fovy, GLdouble aspect,  
  2. GLdouble near, GLdouble far); 

创建一个表示对称透视视图平截头体的矩阵,并把它与当前矩阵相乘。fovy是yz平面上视野的角度,它的值必须在[0.0, 180.0]的范围之内。aspect是这个平截头体的纵横比,也就是它的宽度除以高度。near和far值分别是观察点与近侧裁剪平面以及远侧裁剪平面的距离(沿z轴负方向),这两个值都应该是正的。

前面一段内容提到了英寸和毫米这些单位,它们真的和OpenGL有关的吗?答案是否定的。投影和其他变换在本质上是没有单位的。如果我们想把近侧和远侧裁剪平面看成是位于1.0和20.0m(或英寸、km等其他长度单位),那也没有关系。唯一的规则是必须使用一致的测量单位。最终绘制好的图像将会进行缩放。

原创粉丝点击