1、第第9 9章章 OpenGLOpenGL环境下图形系统的设计环境下图形系统的设计OpenGLOpenGL概述概述1OpenGLOpenGL的功能和基本算法的功能和基本算法2OpenGLOpenGL基本图元绘制和图形几何变换基本图元绘制和图形几何变换3OpenGLOpenGL的交互操作、观察流程和函数的交互操作、观察流程和函数4OpenGLOpenGL中自由曲线和曲面的绘制、多边中自由曲线和曲面的绘制、多边形的消隐形的消隐5OpenGLOpenGL的真实感图形绘制和演示系统的设计的真实感图形绘制和演示系统的设计6本章知识结构图本章知识结构图9.1 9.1 概概 述述 OpenGL经过对GL的进一
2、步展,实现二维和三维的高级图形技术,在性能上表现得异常优越。它的功能包括建模、变换、光线处理、色彩处理、动画以及更先进的能力,如纹理影射、物体运动模糊等。OpenGL的这些能力为实现逼真的三维渲染效果、建立交互的三维景观等提供了条件。9.2 OpenGL9.2 OpenGL应用程序的工作过程应用程序的工作过程 作为图形硬件的软件接口,OpenGL最主要的工作就是将二维及三维物体描绘至帧缓存中。这些物体由一系列的描述物体几何性质的顶点(Vertex)或描述图像的像素(Pixel)组成。OpenGL执行一系列的操作后把这些数据最终转化成像素数据,并在帧缓存中形成最后的结果。OpenGL的工作主要如
3、下:1)图元操作图元操作 OpenGL提供多种模式绘制图元(Primitive),而且一种模式的设置一般不会影响其他模式的设置。2)图形控制图形控制 OpenGL提供诸如变换矩阵、光照、反走样方法、像素操作等来控制二维和三维图形的绘制。然而,它并不提供一个描述或建立复杂几何物体的手段。OpenGL提供的是怎样画复 3)OpenGLOpenGL指令解释模型指令解释模型 OpenGL的指令解释模型是客户机/服务器模式。4)OpenGLOpenGL基本操作基本操作 OpenGL可以在具有不同图形能力和性能的图形工作站平台及计算机上运行。技术难点技术难点模型绘制模型绘制颜色模式的颜色模式的指定指定模型
4、观察模型观察9.3 OpenGL9.3 OpenGL的功能的功能光照应用光照应用图像效果增强图像效果增强位图和图像处理位图和图像处理纹理映射纹理映射实时动画实时动画交互技术交互技术OpenGL的具体的功能主要有以下这些内容:1)模型绘制模型绘制。OpenGL能够绘制点、线和多边形。2)模型观察模型观察。观察三维模型是通过一系列的坐标变换进行的。模型的坐标变换使观察者能够在视点位置观察与视点相适应的三维模型景观。3)颜色模式的指定颜色模式的指定。OpenGL应用了专门的函数来指定三维模型的颜色。4)光照应用光照应用。用OpenGL绘制的三维模型必须加上光照才能更加与客观物体相似。5)图像效果增强
5、图像效果增强。OpenGL提供了一系列增强三维景观的图像效果的函数,这些函数通过反走样、混合和雾化来增强图像的效果。6)位图和图像处理位图和图像处理。OpenGL提供了专门对位图(单色)和图像(彩色)进行操作的函数。7)纹理映射纹理映射。三维景物因缺少景物的具体细节而显得不够真实,为了更加逼真地表现三维景物,OpenGL提供了纹理映射的功能。8)实时动画。实时动画。9)交互技术交互技术。OpenGL提供了方便的三维图形人机交互接口,用户可以选择修改三维景观中的物体。9.4 OpenGL9.4 OpenGL的基本语法规则的基本语法规则9.4.1 OpenGL9.4.1 OpenGL的数据类型的数
6、据类型 为了更容易地将OpenGL代码从一个平台移植到另一个平台,OpenGL定义了它自己的数据类型,OpenGL定义的命令前缀和数据类型如下表9.1所示9.4.2 OpenGL9.4.2 OpenGL的函数约定的函数约定 OpenGL函数都遵循一个命名约定,该约定会告诉你,函数来自于哪一个库,并且常常还会告诉你该函数需要多少个参数以及各个参数的类型。所有函数都有一个根段,代表该函数相应的OpenGL命令。如图9.2所示,glColor3f函数的根段是Color,gl前缀代表gl库,3f后缀表示该函数使用3个浮点参数。所有的 OpenGL函数都采用以下格式:9.5 OpenGL9.5 Open
7、GL基本图元绘制基本图元绘制点点线线多边形多边形字符字符 无论OpenGL绘制的3D画面多么复杂和优美,实质上它们都是由许许多多的点、线、多边形等基本几何对象构成的,而这也是OpenGL可以提供的最基本的绘制功能。图像9.5.1 9.5.1 概述概述 在OpenGL中,最基本的图元就是点,每个几何实体都是由一个顶点集和绘制图元的类型描述的。顶点间是否连接或怎样连接是由几何图元的类型决定的。OpenGL中所有的实体最终都可采用一系列有序的顶点描述。OpenGL虽然分别提供了二维和三维顶点的绘制方法,但二维图形不过是三维图形的特殊情况(z分量为0),在三维顶点绘制指令中,如果用户设定二维坐标(x,
8、y),OpenGL就会自动令z=0。因此,这里将三维基本图元和二维基本图元放在一起介绍。OpenGL提供的描述点、线、多边形的绘制机制必须通过glBegin()和glEnd()函数配对来完成,两个函数如下所示。void void glBeginglBegin(GLenumGLenum mode)mode)功能:功能:描述一个几何图元顶点序列的开始。void void glEndglEnd(void)(void)功能:功能:标记顶点表的结束。在OpenGL中,所有的图元绘制都是在这对函数中完成的。几何图元类型和说明图如下:9.5.2 9.5.2 点点 1 1点的绘制点的绘制OpenGL中的点定义
9、为一个方块,默认状态下,一般的绘制点就是绘制显示屏幕的一个像素。在OpenGL中一个点是当作一个n维(n=2,3,4)向量来处理的。如果调用函数用glVertex2f(2.0,1.0)指定一个顶点的坐标(2.0,1.0),则在实际计算中OpenGL是处理点(2.0,1.0,0.0),即OpenGL中用二维向量表示的点自动地将这个点的z值赋以0.0。用函数glVertex()可定义一个点,下面具体介绍这个函数。glVertexglVertex2,3,42,3,4sifdsifd(V)(TYPE(V)(TYPE coordscoords)2 2点的大小点的大小 OpenGL提供了可以控制点的大小的
10、函数。点大小的默认值是一个像素。可以用函数glPointsize()修改这个值,以设定点的大小:void glPointsize(GLfloat size)是否启动反走样,对绘制点操作有一定影响。如果没有启动反走样,所绘制的点是一个正方形块,浮点数四舍五入为整数宽度;如果启动反走样,则画一个圆形像素集,边界像素用低的颜色强度绘制,用浮点数不进行四舍五入,从而使所画的点看上去很光滑。1 1直线的绘制直线的绘制我们知道,两个点可以确定一条直线,下面的代码在两个点(0,0,0)和(50,50,50)之间画一根直线。glBegin(GL_LINES);glVertex3f(0.0,0.0,0.0)gl
11、Vertex3f(50.0,50.0,50.0)glEND();注意:在OpenGL中,参数GL_LINES对每两个指定的顶点画一根直线。如果GL_LINES指定奇数个顶点,那么最后一个顶点将会被忽略。2 2折线和封闭折线的绘制折线和封闭折线的绘制用以下的指令可以绘制折线和封闭折线。在指定GL_LINES_STRIP时,可从一个顶点到另一个顶点用连续的线段画线。例如,在xy平面上画两条由三个顶点指定的线,如图9.4所示:9.5.3 9.5.3 线线 9.5.4 9.5.4 多边形多边形 1 1多边形的绘制多边形的绘制 多边形是指由封闭线段围成的区域。但OpenGL中的多边形有两点限制:(1)多
12、边形的边不能自相交,即边和边除了多边形的顶点外不可以相交;(2)多边形必须是凸多边形。这些限制是为特别需要设制的。首先所有的多边形都可以分割为多个凸多边形。限制多边形的类型容易实现硬件加速。2图案填充 多边形可以是以多种方式填充的多边形,OpenGL提供了定义多边形的点画样式的函数glPolygonStipple(),下面具体介绍。glPolygonStipple(glubyte*mask)参数说明:mask指向一个3232位图的指针。另外还有两个相关函数。glEnable(GL_POLYGON_STIPPLE):启动多边形点画式样。glDisable(GL_POLYGON_STIPPLE):
13、关闭多边形点画式样。OpenGL本身没有附带字体的支持,而OpenGL体系结构评审委员会也很少涉及这方面的讨论。OpenGL参考协议(OpenGL Specification)也没有关于字体的讨论信息。但字体是必不可少的,在OpenGL中可以使用其他方法来渲染字体,这里有两种方法:位图、画轮廓(多边形)。每种方法有其自己的优点与缺点。对于处理场景中独立旋转及缩放的标题而言,选择位图字体是比较理想的。从本质上来说,它是预先光栅化的,所以渲染速度比较快,使用它们对提高程序执行速度是显而易见的。轮廓字体主要用于描述带控制点及曲线集合的字符特征。具体操作与OpenGL处理多边形是一致的。9.5.5 9
14、.5.5 字符字符9.6 OpenGL9.6 OpenGL图形的几何变换图形的几何变换矩阵操作函数矩阵操作函数几何变换几何变换OpenGLOpenGL视区变换视区变换 矩阵操纵函数如下:1.1.void void glLoadIdentityglLoadIdentity(void)(void)功能:功能:设置当前操作矩阵为单位矩阵(当前矩阵即为以后图形变换所要使用的 矩阵)。2.void 2.void glLoadMatrixglLoadMatrix fdfd(const TYPE(const TYPE*m)m)功能:功能:设置任意的矩阵为当前的操作矩阵。参数说明:参数说明:m是一个单精度或双
15、精度浮点数指针,指向一个按列存储的44矩阵。3 3.void void glMultMatrixglMultMatrix fdfd(const TYPE(const TYPE*m)m)功能:功能:用当前矩阵乘以这个函数所提供的矩阵,并且把结果置为当前矩阵。参数说明:参数说明:m是一个单精度或双精度浮点数指针,指向一个按列存储的44矩阵。4 4.void void glPushMatrixglPushMatrix()()功能:功能:将当前矩阵压入矩阵堆栈。5 5.void void glPopMatrixglPopMatrix()()功能:功能:将当前矩阵弹出矩阵堆栈。运用以上的函数,如果有特殊
16、的需要,用户就可以定义自己的变换。9.6.1 矩阵操作函数1平移变换平移变换 平移变换函数如下:void glTranslatefd(TYPE x,TYPE y,TYPE z)三个函数参数x、y和z就是几何物体分别沿三个轴向平移的偏移量。这个函数表示用这三个偏移量生成的矩阵乘以当前矩阵。当参数是(0.0,0.0,0.0)时,表示对函数glTranslate*()的操作是单位矩阵,也就是对物体没有影响。2旋转变换旋转变换 旋转变换函数如下:void glRotatefd(TYPE angle,TYPE x,TYPE y,TYPE z)该命令用四个参数所构成的矩阵R乘以当前矩阵。如果参数angle
17、为零,该命 令不作 用。3比例变换比例变换比例变换函数如下:void glScalefd(TYPE x,TYPE y,TYPE z)参数表示变换对象分别沿三个坐标轴缩放的比例因子。该命令把三个比例因子形 成的矩阵S乘以当前矩阵。变换对象中的每个点的在x、y和z轴上的坐标都要乘上 相应的参数x、y、z。9.6.2 9.6.2 几何变换几何变换9.7 OpenGL9.7 OpenGL的交互操作的交互操作反馈反馈物体的选择物体的选择 9.7.1 9.7.1 物体的选择物体的选择 选择物体事实上是响应OpenGL应用程序的一个拾取事件,该事件通常是由鼠标来触发的。为此,应用程序必须建立物体的名称集合,
18、并将名称加以适当组织。然后当发生捡取事件时,就对其进行响应。当拾取一个物体后,就以记录的形式组织相关信息并返回给应用程序。物体的选择集合是用物体的名称堆栈来管理的,建立名称堆栈的步骤如下:(1)用glSelectBuffer()指定用于返回命令中记录的数组。(2)以glRenderMode(GL_SELECT)函数进入选择模式。(3)用glInitName()和glPushName()初始化名称堆栈。(4)定义用于选择的视见体。并用glPickMatrix()设定选择区域的范围。(5)依照绘图模式下场景的绘制步骤原样绘制场景。(6)用glRenderMode(GL_RENDER)函数退出选择模
19、式。9.7.2 9.7.2 反馈反馈 信息反馈为程序设计提供了重要的运行资料。在反馈模式下,每个被光栅化的基元均产生一组数据,并由OpenGL把它们存放入反馈数组中,每组数据均有一个标记,该标记说明了基元的类型,接着是描述基元的顶点坐标值、其他如颜色和纹理等相关数据。与选择模式相同的是,反馈模式不对像素进行任何光栅化操作,也不向帧缓存写入任何绘图信息,因而在应用反馈模式之前,必须绘制一次需要反馈信息的物体。应用反馈模式的基本步骤如下:(1)确定反馈信息的信息类别和反馈数组。反馈数组应是一个存储浮点值的数组,由glFeedbackBuffer()函数来完成,其原型为:void glFeedbac
20、kBuffer(CLsizei size,CLenum type,GLfloat*buffer);其中,size参数表示能够写进反馈数组的数据的最大个数;type参数为一个标记常数,它表明OpenGL应该返回顶点的那些数据,可以取的值如下:GL-2D、GL-3D、GL-3D-COLOR、GL-3D-COLOR-TEXTURE及GL-4D-COLOR-TEXTURE,其含义说明如下:GL-2D只返回顶点的几何坐标(x,y)GL-3D只返回顶点的几何坐标(x,y,z)。GL-3D-COLOR返回顶点的几何坐标(x,y,z)及顶点的颜色。若颜色为RGBA模式,则颜色分量的个数为4,这样该组数据的个数
21、为7。GL-3D-COLOR-TEXTURE返回顶点的几何坐标(x,y,z)、顶点的颜色与纹理值。纹理由4个量组成。这样在RGBA模式下,该组数据的个数为11个。GL-4D-COLOR-TEXTURE返回顶点的被剪切后的几何坐标(x,y,z,w)、顶点的颜色和纹理值。这样在RGBA模式下,该组数据的个数为12个。(2)将glRenderMode()函数的参数设为GL-FEEDBACK,使OpenGL进入反馈模式。(3)重新绘制物体,并按要求插入标记。重新绘制物体时,并不向帧缓存写入绘图信息。(4)退出反馈模式,处理反馈数据。9.8 OpenGL9.8 OpenGL观察流程和函数观察流程和函数计
22、算机图形系统模视变换常用的变换函数投影变换视区变换附加裁剪面OpenGL观察流程如下图所示。9.8.1 9.8.1 常用的变换函数常用的变换函数 变换函数说明如下:void void glMatrixModeglMatrixMode(GlenumGlenum mode);mode);功能:功能:该函数指定哪一种矩阵为当前矩阵。参数说明:参数说明:mode指定当前矩阵的类型。可以有下面三种类型:GL_MODELVIEW后继的操作均在模视(modelview)变换范围内。GL_PROJECTION后继的操作均在投影变换范围内。GL_TEXTURE后继的操作在纹理映射范围内。某一时刻只能处于其中的一
23、种状态。默认时,处于GL_MODELVIEW状态。void glLoadIdentity(void);功能:功能:该函数设置单位矩阵为当前矩阵。void glLoadMatrixfd(const TYPE*m);功能:功能:该函数用任意44矩阵替代当前矩阵。参数说明:参数说明:m指定任意矩阵的16个元素void glMultMatrixfd(const TYPE*m);功能:功能:该函数用任意44矩阵乘当前矩阵参数说明:参数说明:m指定任意矩阵的16个元素参数m为指定矩阵M,M由16个值的向量(m0,m2,m15)组成 9.8.2 9.8.2 模视变换模视变换 1 1变换的顺序变换的顺序 当执
24、行变换A和B时,如果按不同顺序执行,则结果往往会大不相同。例如变换A为旋转45角,变换B为向x轴方向移动一个距离,不同的执行顺序产生不同的结果,如下图9.6所示。2模型变换 模型变换有三个基本的OpenGL命令:glTranslateglTranslate*()()平移平移 glRotateglRotate*()()旋转旋转 glScaleglScale*()()缩放缩放 3观察变换 观察变换改变视点的位置和方向,也就是改变观察坐标系(眼坐标系)。在世界坐标系中,视点和物体的位置是一个相对的关系,对物体作一些平移、旋转变换,必定可以通过对视点作相应的平移、旋转变换来达到相同的视觉效果。完成视图
25、变换可以有以下几种方法:利用一个或几个模型变换命令(即glTranslate*()和glRotate*()。利用实用库函数gluLookAt()设置观察坐标系。创建封装旋转和平移命令的实用函数。如下图9.7所示:9.8.3 9.8.3 投影变换投影变换 投影变换就是要确定一个取景体积,其作用有两个:(1)确定物体投影到屏幕的方式,即是透视投影还是平行(正交)投影。(2)确定从图像上裁剪掉哪些物体或物体的某些部分。投影变换包括透视投影和平行投影(正交投影)。1 1透视投影透视投影 透视投影的示意图如图9.8所示:2.2.平行平行(正交正交)投影投影平行(正交)投影的示意图如下图所示,void v
26、oid glViewportglViewport(Glint(Glint x,Glintx,Glint y,Glsizey,Glsize width,Glsizewidth,Glsize height);height);功能:功能:该函数设置视区的大小。参数说明:参数说明:x,y指定视区矩形的左下角坐标(以像素为单位)。默认值为(0,0)width,height分别指定视区的宽和高。void void glDepthRangeglDepthRange(GlclampedGlclamped near,near,GlclampedGlclamped far);far);功能:功能:该函数指定从规格
27、化设备坐标到窗口的z值(深度值)映射。参数说明:参数说明:near指定映射到窗口坐标的近裁剪面,默认值为0;far指定映射到窗口坐标的 远裁剪面,默认值为1。near和far值表示可存储在深度缓存中的最小和最大值的配置。默认值依次为0.0和1.0,大多数应用可利用默认值。9.8.4 9.8.4 视区变换视区变换 视区就是窗口中矩形绘图区。用窗口管理器在屏幕上打开一个窗口时,已经自动地把视区设为整个窗口的大小,可以用glViewport命令设定一个较小的绘图区,利用这个命令还可以在同一窗口上同时显示多个视图,达到分屏显示的目的。函数说明如下:9.8.5 9.8.5 附加裁剪面附加裁剪面 除了视见
28、体的六个裁剪面(左、右、底、顶、近和远)外,OpenGL还能定义最多6个附加的裁剪面来进一步限制视图体,如下图9.10所示。附加裁剪面可用于显示物体的剖面图。每个裁剪面通过指定方程Ax+By+Cz+D=0中的系数来确定的。裁剪面通过造型和视图变换自动进行相应的变换。最后的裁剪体成为视见体和附加裁剪面所定义的全部半空间的相交的立体空间。void void glClipPlaneglClipPlane(GlenumGlenum plane,const plane,const GldoubleGldouble *equation);equation);功能:功能:该函数定义附加裁剪面。参数说明:参数
29、说明:plane用符号名GL_CLIP_PLANEi指定裁剪面,其中i为0和5之间的整数,指定6个裁剪面中的一个;equation指定4个值的数值,存放平面方程的4个参数。9.9 OpenGL9.9 OpenGL中自由曲线和中自由曲线和曲面的绘制曲面的绘制 9.9.1 Bezier9.9.1 Bezier曲线的绘制曲线的绘制 Bezier曲线是一种以逼近为基础的参数曲线,它是由一组Bezier特征多边形来定义的。曲线的起点和终点与该多边形的起点和终点重合,且多边形的第一条边和最后一条边分别表示了曲线在起点和终点处的切向矢量方向。曲线的形状则趋于多边形的形状。多边形可由其顶点来定义。这些顶点则被
30、称为控制点。只要给出控制点,就可生成一条Bezier曲线。1 1曲线的定义与激活曲线的定义与激活 在OpenGL中,曲线和曲面的构造是借助于OpenGL求值器来完成的。要生成一条曲线,首先,要创建一个求值器。其次,要激活求值器,使其进曲线映射。最后,要将求值器生成的各顶点连接起来则可以生成一条完整的曲线。创建一维评价器的函数为glMap1d()或g1Map1f(),由它们生成所需坐标值。glMap1d()函数原型为:void glMap1d(GLenum target,GLdouble u1,GLdouble u2,Glintstride,GLint order,const GLdouble*
31、points);target参数表如下表图示:2曲线坐标的计算 为了能生成一条曲线,还要进行曲线坐标的计算和连接。该函数为 glEvalcoord1d()或glEvalCoord1f()。以glEvalcoord1d()为例,其原型为:void glEvalcoord1d(void glEvalcoord1d(GLDoubleGLDouble u);u);3定义均匀间隔曲线坐标值 OpenGL允许对u参数区间进行自动等分,以获得等间距的曲线上的点。该函数为GlMapGrid1d()或glMapGrid1f()。以glMapGrid1d()函数为例,其原型为:Void Void glMapGri
32、dldglMapGridld(Glint un(Glint un,GLdoubleGLdouble ulul,GLdoubleGLdouble u2)u2);9.9.2 Bezier9.9.2 Bezier曲面的绘制曲面的绘制 计算机图形学中的所有光滑曲面都采用多边形逼近来绘制,而且许多有用的曲面在数学上也只用少数几个参数(如控制点或网等)来描述。通常,用16个控制点描述一个曲面要比用1000多个三角形和每个顶点的法向信息要节省很多内存。而且,1000个三角形仅仅只逼近曲面,而控制点可以精确地描述实际曲面,且可自动计算法向。下面简要地介绍OpenGL中Bezier曲面的绘制方法,所有相关的函数
33、都与曲线的情况类似,只是二维空间而已。曲面定义函数为 Void glMap2Void glMap2fdfd(GLenumGLenum target,TYPEtarget,TYPE u1,TYPE u2,Glint u1,TYPE u2,Glint ustride,GLintustride,GLint uorder,TYPEuorder,TYPE v1,TYPE v2,GLint v1,TYPE v2,GLint vstride,GLintvstride,GLint vorder,TYPE points);曲面坐标计算函数为:void glEvalCoord2void glEvalCoord2f
34、dfdv(TYPE v(TYPE u,TYPEu,TYPE v);v);产生曲面坐标并绘制。参数u和v是定义域内的值。9.9.3 NURBS9.9.3 NURBS曲线的绘制曲线的绘制 在OpenGL中,GLU函数库提供了一个NURBS接口,该接口连接OpenGL求值器,并通过求值器连接OpenGL的内核,最终实现用户交互。用户需要提供的重要数据包括控制点、节点和纹理等数据。控制点说明曲线的大致走向,而节点则控制B样条函数的形状,从而最终控制曲线的形状。绘制一个NURBS曲线至少要完成如下步骤:提供控制点序列和节点序列;创建一个NURBS对象,设置NURBS对象属性;绘制曲线。创建一个NURBS
35、对象,首先应定义一个NURBS对象指针,然后用gluNewNurbsRender()函数来创建。函数形式为:GLUnurbsObj*theNurb;TheNurb=gluNewNurbsRender();在此之后,应设置NURBS对象的属性,通过gluNurbsPropety()函数来完成。该函数的原型为:void gluNurbsPropety(GLUnurbsObj*nobj,GLenum propety,GLfloat value);pmpety参数如下表所示:9.9.4 NURBS曲面的绘制绘制一个NURBS曲面的步骤如下:(1)生成几何控制点序列及节点序列。(2)生成纹理控制点序列及
36、节点序列。(3)生成法线控制点序列及节点序列(也可自动生成)。(4)创建NURBS对象并确定该对象的属性。(5)进行纹理映射。(6)进行光照。(7)激活各种所需特定功能。(8)绘制曲面。(9)挂起各种已用特定功能。9.10 OpenGL9.10 OpenGL中的多边形的消除与消隐中的多边形的消除与消隐计算机图学计算机图学的发展方向的发展方向人人机交互机交互技术技术造型技术真实图形生成技术 9.9.4 NURBS曲面的绘制 在OpenGL中,多边形分为正面和反面,在使用多边形的过程中可以对多边形的两个面分别进行操作。OpenGL中提供多边形两面操作的命令就可以解决这个问题。默认状态下OpenGL
37、对多边形正反面是以相同的方式绘制的,要改变多边形的绘制状态,必须调用函数glPolygonMode(),函数说明如下:g glPolygonModelPolygonMode(GLenumGLenum face,GLenumface,GLenum mode)mode)功能:功能:该函数控制多边形反面或正面的绘图模式。参数说明:参数说明:face:指定多边形的面。face可能的值是GL_FRONT、GL_BACK和GL_FRONT_AND _BACK。其中GL_FRONT指定多边形的正面,GL_BACK指定多边形的反面,GL_FRONT_AND_BACK指定多边形的正面和反面。mode:指定指定面
38、的模式。表9-9说明了mode的可能值及其功能。g1FrontFace(g1FrontFace(GlenumGlenum mode)mode)功能功能:指定多边形的正面。参数说明参数说明:mode可以为GL_CCW或GL_CW。glCullFaceglCullFace(GlenumGlenum mode)mode)功能功能:指出在转换成屏幕坐标之前,哪些多边形应该被消除。参数说明参数说明:mode:可以是GL_FRONT、GL_BACK和GL_FRONT_AND_BACK,用来指定正向、反向或所有的多边形。默认状态是GL_BACK。void void glClearDepthglClearDe
39、pth(GLclmpdGLclmpd depth)depth)功能功能:指定在刷新深度缓冲器时所用的深度值。也就是刷新深度缓冲器后,深度缓冲器为窗口中的每一个像素点设置的深度值。参数说明参数说明:depth:指定刷新深度缓冲器时所用的深度值。void void glDepthFuncglDepthFunc(GlenumGlenum FuncFunc)功能功能:在消隐操作中设置比较函数。参数说明参数说明:Func:指定比较规则,9.11 OpenGL9.11 OpenGL的真实感图形绘制的真实感图形绘制 9.11.1 OpenGL9.11.1 OpenGL颜色颜色 OpenGL颜色模式有两种:R
40、GB(RGBA)模式和颜色表模式。在RGB模式下,所有的颜色定义全用R、G、B三个值来表示,有时也加上Alpha值(与透明度有关),即RGBA模式。在颜色表模式下,每一个像素的颜色是用颜色表中的某个颜色索引值表示的,而这个索引值指向了相应的R、G、B值。这样的一个表称为颜色映射(Color Map)。1.RGBA1.RGBA模式模式在RGBA模式下,可以用glColor*()来定义当前颜色。其函数形式为 void glColor3b s i f d ub us ui(TYPE r,TYPE g,TYPE b);void glColor4b s i f d ub us ui(TYPE r,TYP
41、E g,TYPE b,TYPE a);Void glColor3b s i f d ub us uiv(TYPE*v);void glColor4b s i f d ub us uiv(TYPE*v);这个函数有glColor3和glColor4两种方式 2 2颜色表模式颜色表模式 在颜色表模式下,可以调用glIndex*()函数从颜色表中选取当前颜色。其函数形式为:void glIndexsifd(TYPE c);void glIndexsifdv(TYPE*c);此函数用于设置当前颜色索引值,即调色板号。若值大于颜色位面数,则取模。9.11.2 OpenGL光照 1OpenGLOpenGL
42、光组成光组成 在OpenGL简单光照模型中的几种光分别为:辐射光(Emitted Light)、环境光(Ambient Light)、漫射光(Diffuse Light)、镜面光(Specular Light)。辐射光是最简单的一种光,它直接从物体发出并且不受任何光源影响。环境光是由光源发出经环境多次散射而无法确定其方向的光,即似乎来自所有方向。镜面光来自特定方向并沿另一方向反射出去,一个平行激光束在高质量的镜面上产生100%的镜面反射。2 2创建光源创建光源 光源有许多特性,如颜色、位置、方向等。选择不同的特性值,则对应的光源作用在物体上的效果也不一样,这在以后的章节中会逐步介绍的。下面详细
43、讲述有关光源特性的函数。1)创建光源 OpenGL中定义光源是由函数glLight*()实现的,下面具体说明这个函数。void void glLightglLight f,if,iv(v(GLenumGLenum light,light,GLenumGLenum pname,GLfloatpname,GLfloat *paramparam)2)启动/关闭光照 在OpenGL中,必须明确指出光照是否有效或无效。如果光照无效,则只是简单地将当前颜色映射到当前顶点上去,不进行法向、光源、材质等复杂计算,那么显示的图形就没有真实感。要使光照有效,首先得启动光照,即 glEnableglEnable(G
44、L_LIGHTINGiGL_LIGHTINGi););若使光照无效,则调用:glDisableglDisable(GL_LIGHTINGiGL_LIGHTINGi)关闭当前光照。9.11.2 OpenGL光照 在OpenGL中,用单一颜色处理的称为平面明暗处理(Flat Shading),用许多不同颜色处理的称为光滑明暗处理(Smooth Shading),也就是Gourand明暗处理(Gourand Shading)。设置明暗处理模式的函数为:void void glShadeModelglShadeModel(GLenumGLenum mode);mode);函数参数为GL_FLAT或GL
45、_SMOOTH,分别表示平面明暗处理和光滑明暗处理。9.11.4 OpenGL9.11.4 OpenGL纹理映射纹理映射 OpenGL中纹理映射是一个相当复杂的过程,这里只简单地叙述一下最基本的执行纹理映射所需的步骤。基本步骤如下:(1)定义纹理。(2)控制滤波。(3)说明映射方式。(4)绘制场景,给出顶点的纹理坐标和几何坐标。注意:纹理映射只能在RGBA方式下执行,不能运用于颜色表方式。1 1纹理定义纹理定义 1)一维纹理定义函数 void glTexImage1D(void glTexImage1D(GlenumGlenum target,GLinttarget,GLint level,G
46、lintcomponents,GLsizeilevel,Glintcomponents,GLsizei width,GLintwidth,GLint border,GLenumborder,GLenum format,format,GLenumGLenumtype,consttype,const GLvoidGLvoid *pixels);pixels);2)二维纹理定义的函数 void glTexImage2D(void glTexImage2D(GLenumGLenum target,GLinttarget,GLint level,GLintlevel,GLint components,c
47、omponents,GLsizeiGLsizei width,glsizeiwidth,glsizei height,GLintheight,GLint border,GLenumborder,GLenum format,GLenumformat,GLenum type,type,const const GLvoidGLvoid *pixels);pixels);2 2纹理控制纹理控制 OpenGL中的纹理控制函数是:void void glTexParameterglTexParameterifv(ifv(GLenumGLenum target,GLenumtarget,GLenum pna
48、me,TYPEpname,TYPE paramparam););1)滤波 一般来说,纹理图像为正方形或长方形。但当它映射到一个多边形或曲面上并变换到屏幕坐标时,纹理的单个纹素很少对应于屏幕图像上的像素。根据所用变换和所用纹理映射,屏幕上单个像素可以对应于一个纹素的一小部分(即放大)或一大批纹素(即缩小)。下面用函数glTexParameter*()说明放大和缩小的方法:glTexParameterglTexParameter*(GL_TEXTURE_2D,(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);GL_TEXTURE_MAG_FILTER
49、,GL_NEAREST);glTexParameterglTexParameter*(GL_TEXTURE_2D,(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);GL_TEXTURE_MIN_FILTER,GL_NEAREST);2)重复与约简 纹理坐标可以超出(0,1)范围,并且在纹理映射过程中可以重复映射或约简映射。在重复映射的情况下,纹理可以在s,t方向上重复,即 glTexParameterfvglTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);(GL_TEXTURE_
50、2D,GL_TEXTURE_WRAP_S,GL_REPEAT);glTexParameterfvglTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);3映射方式 在实际编程中,纹理图像经常是直接作为画到多边形上的颜色来处理。实际上,可以用纹理中的值来调整多边形(曲面)原来的颜色,或用纹理图像中的颜色与多边形(曲面)原来的颜色进行混合。OpenGL提供了3种纹理映射的方式,这个函数是:void void glTexEnvglTexEnvifv(