OpenGL编程基础之三

4.1 摄像机与对象

将三维图形系统形成图像的过程概念化的基本模式称为合成摄像机模型(synthetic camera model)。我们需要两个独立的实体:一个几何对象集以及这些对象的观察者。每个实体都可彼此独立地进行指定。

将对象的规格和摄像机整合的过程称为投影(projection),该过程是由OpenGL在其流水线内部完成的。称为投影线(projector)的直线穿过图像中的每一点,并经过摄像机的光心(投影中心)。经过对象上某一点的投影线与焦平面的交点即为该点在图像中的投影点所在的位置。焦平面移到摄像机的前方,这就避免了由透镜引起的图像倒置。我们只需要指定摄像机和场景中的物体。OpenGL将在其实现内部替我们完成该项工作。

为了描述摄像机的位置和方向,我们需要6个参数(6个自由度)。我们还需要对摄像机的透镜进行设置(法线、广角或长焦),而且不同的摄像机的底片尺寸也有差异。

一旦对摄像机指定了位置和朝向,投影过程只需要完成两部分内容。第一部分是确定哪些对象可见,那些不可见。OpenGL的观察函数定义了一个视域体(或裁剪体),以模拟真实摄像机通过透镜所能观察到的空间。所有位于该视域体外的物体将不会出线在图像中,我们称这些对象被“裁剪”掉了。在计算机图形学中,人为地增加了一个前裁剪面(近裁剪面)和后裁剪面(远裁剪面)。这样,该裁剪体的形状就是一个被截掉头部的金字塔,称其为视域体(frustum,平截头体)。第二部分是确定位于裁减体内的对象上的某个特定位置的图像在投影平面中的位置。

4.2 OpengGL中的正交投影

我们可将正交投影(orthographic projection 或 orthogonal projection)看作模拟长焦镜头拍摄图像的方式。这种类型的图像看起来缺乏立体感,但具有保持距离和形状的特点。当我们将摄像机移到距离拍摄对象无穷远处,但投影平面在对象附近时,就可得到正交投影图像。当物距无穷大时,所有的投影线都彼此平行,投影中心将被投影方向所取代。此时视域体演变为一个直平行六面体(right parallelepiped)

4.4 摄像机的定位

给定视点(观察点),将立方体旋转,并使其偏离原点,我们可用三种方式来实现这一过程。第一种方法是计算立方体各顶点的新位置。第二种方法是使用变换。第三种方法使用gluLookAt()函数。

4.5.2 顶点数组

OpenGL提供了一个称为顶点数组(vertex array)的工具,它扩展了数组的使用方式,可以显著减少绘制立方体时的函数调用的次数。其主要思想是存储在数组中的信息可被存储在客户端(应用程序)中,并可通过单次函数调用来访问。

OpenGL6种类型的数组提供了支持:顶点、颜色、颜色索引、法线、纹理坐标以及边标记。使用顶点数组需要三个步骤。首先,像其他OpenGL特性一样,必须将其启用。其次,必须指定数组的格式。这通常是程序初始化阶段的一部分。最后,用该数组来绘制场景。

我们也可用显示列表来减少绘制的代价,只需调用一次glCallList()函数。

4.6 消隐

如何确保在所绘制的图像中只有观察者能够看见的表面是可见的。在一些情况下,如对于凸对象,我们只是选择不对背面朝向的多边形进行绘制。我们也可考虑使用画家算法(painter's algorithm),其思想是如果我们依据到摄像机的距离将多边形进行排序,并按照自后向前的顺序对这些多边形进行绘制,则位置靠前的多边形将位于其后的多边形遮挡。但它不适用于流水线绘制器。

OpenGL所使用的消隐方法称为z缓存算法(z-buffer algorithm)或深度缓存算法。该算法需要借助额外的存储空间来保存在绘制过程中绘制器已经绘制的多边形的深度信息。这个额外的存储空间称为z或深度缓存。

在初始化阶段,我们必须先请求一个深度缓存:

glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

启用深度缓存:

glEnable(GL_DEPTH_TEST);

最后,当我们清空颜色缓存时,通常也将深度缓存清空:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

4.8透视投影

OpenGL提供了函数glFrustum()用于创建所需的透视投影矩阵。与正交投影不同(摄像机可位于裁减体内部),在透视投影中,视域体必须位于摄像机前方。所有的参数都是相对摄像机坐标系中定义的,所以nearfar都必须为正,且far的值应大于near

使用透视投影的一个潜在问题是深度精度的损失,在显示设备中该问题可能非常明显。该问题的根源在于深度缓存中位深度的限制以及由透视投影引起的非线性比例变换。

posted @ 2011-11-20 20:11  杨溪  阅读(2945)  评论(0编辑  收藏  举报