1、第第10章章 OpenGL10.1 简介简介10.2 OpenGL基本程序结构基本程序结构10.3 OpenGL程序设计入门程序设计入门10.1 简介简介10.1.1 什么是什么是OpenGL?OpenGL是一个功能强大的是一个功能强大的开放开放图形库图形库(Open Graphics Library)。其。其前身是前身是SGI公司为其图形公司为其图形工作站开发的工作站开发的IRIS GL。为使其能够更加容易地。为使其能够更加容易地移植到不同的硬件和操作系统,移植到不同的硬件和操作系统,SGI开发了开发了OpenGL。目前,目前,OpenGL已成为开放的国际图形标准。已成为开放的国际图形标准。
2、10.1.2 OpenGL的特点的特点从程序开发人员的角度来看,从程序开发人员的角度来看,OpenGL是一组是一组绘图命令的绘图命令的API集合。利用这些集合。利用这些API能够方便地能够方便地描述二维和三维几何物体,并控制这些物体按描述二维和三维几何物体,并控制这些物体按某种方式绘制到显示缓冲区中。某种方式绘制到显示缓冲区中。OpenGL的的API集提供了物体描述、平移、旋转、缩放、光照、集提供了物体描述、平移、旋转、缩放、光照、纹理、材质、像素、位图、文字、交互以及提纹理、材质、像素、位图、文字、交互以及提高显示性能等方面的功能,基本涵盖了开发二、高显示性能等方面的功能,基本涵盖了开发二、
3、三维图形程序所需的各个方面。与一般的图形三维图形程序所需的各个方面。与一般的图形开发工具相比,开发工具相比,OpenGL具有以下几个突出特具有以下几个突出特点点:(1 1)跨平台特性)跨平台特性 OpenGL与硬件、窗口和操作系统是相互独立的。与硬件、窗口和操作系统是相互独立的。为了构成一个完整功能的图形处理系统,其设计实现为了构成一个完整功能的图形处理系统,其设计实现共分共分 5 5 层:图形硬件、操作系统、窗口系统、层:图形硬件、操作系统、窗口系统、OpenGL和应用软件。和应用软件。因而,因而,OpenGL可以集成到各种标准窗口和操作可以集成到各种标准窗口和操作系统中。例如,操作系统包括
4、系统中。例如,操作系统包括UNIX,Windows NT,Windows 95/98,DOS等;窗口系统包括等;窗口系统包括X Windows,Microsoft Windows等。等。(2)应用的广泛性应用的广泛性OpenGL是目前最主要的二、三维交互式图形应用程是目前最主要的二、三维交互式图形应用程序开发环境,已成为业界最受推荐的图形应用编程接序开发环境,已成为业界最受推荐的图形应用编程接口。自从口。自从1992年发表以来,年发表以来,OpenGL已被广泛地应用已被广泛地应用于于CAD/CAM、三维动画、数字图像处理以及虚拟现、三维动画、数字图像处理以及虚拟现实等领域,实等领域,Kinet
5、ix公司的公司的3D Studio Max就是突出的就是突出的代表。无论是在代表。无论是在PC机上,还是在工作站甚至是大型机上,还是在工作站甚至是大型机和超级计算机上,机和超级计算机上,OpenGL都能表现出它的高性能都能表现出它的高性能和强大威力。和强大威力。(3)网络透明性网络透明性 建立在客户建立在客户/服务器模型上的网络透明性是服务器模型上的网络透明性是OpenGL的固有特性,它允许一个运行在工作站上的的固有特性,它允许一个运行在工作站上的进程在本机或通过网络在远程工作站上显示图形。利进程在本机或通过网络在远程工作站上显示图形。利用这种性质能够均衡各工作站的工作负荷用这种性质能够均衡各
6、工作站的工作负荷,共同承担共同承担图形应用任务。图形应用任务。(4)高质量和高性能高质量和高性能 无论是在无论是在CAD/CAM、三维动画还是可视化仿真、三维动画还是可视化仿真等领域,等领域,OpenGL高质量和高效率的图形生成能力都高质量和高效率的图形生成能力都能得到充分的体现。在这些领域中,开发人员可以利能得到充分的体现。在这些领域中,开发人员可以利用用OpenGL制作出效果逼真的二、三维图像来。制作出效果逼真的二、三维图像来。(5)出色的编程特性出色的编程特性 OpenGL在各种平台上已有多年的应用实在各种平台上已有多年的应用实践,加上严格的规范控制,因此践,加上严格的规范控制,因此Op
7、enGL具有具有良好的稳定性。良好的稳定性。OpenGL具有充分的独立性与易使用性等。具有充分的独立性与易使用性等。10.2 OpenGL基本程序结构基本程序结构 Windows 95/98以及以及Windows NT 3.51 以上的操以上的操作系统中提供了作系统中提供了OpenGL的动态库,在的动态库,在VC+2.0 以上的版本中提供了以上的版本中提供了OpenGL的静态库,所以,的静态库,所以,使用使用OpenGL编程,在微机上使用时,最好是编程,在微机上使用时,最好是在上述软件环境中编写在上述软件环境中编写OpenGL程序。程序。在微机版本中,在微机版本中,OpenGL 提供了三个函数
8、库,提供了三个函数库,它们是基本库、实用库和辅助库。它们是基本库、实用库和辅助库。10.2.1 Windows系统下的系统下的OpenGL函数函数OpenGL的基本库是的基本库是OpenGL的核心函数库,在这的核心函数库,在这个函数库中,提供了个函数库中,提供了115个函数,这些函数都是以个函数,这些函数都是以“gl”为前缀。为前缀。这类这类API的主要功能包括物体描述、的主要功能包括物体描述、平移、旋转、缩放、光照、纹理、材质、像素、位平移、旋转、缩放、光照、纹理、材质、像素、位图、文字处理等。图、文字处理等。所有所有OpenGL 提供的操作都可以使用这些函数来实提供的操作都可以使用这些函数
9、来实现,而且,对于不同的软件和硬件平台,这些函数现,而且,对于不同的软件和硬件平台,这些函数的使用是完全相同的,这个特性注定了的使用是完全相同的,这个特性注定了OpenGL程程序完美的可移植性。序完美的可移植性。OpenGL的实用库是的实用库是OpenGL基本库的一套子程序,基本库的一套子程序,它提供了它提供了43个函数,这些函数都是以个函数,这些函数都是以”glu”为前缀。为前缀。基本的基本的OpenGL不支持传统上同图形标准相关的一不支持传统上同图形标准相关的一些几何对象,为了减少一些编程负担,些几何对象,为了减少一些编程负担,OpenGL提提供了实用库。供了实用库。主要功能包括绘制二次曲
10、面、主要功能包括绘制二次曲面、NURBS曲线曲面、复杂多边形以及纹理、矩阵管曲线曲面、复杂多边形以及纹理、矩阵管理等。理等。实用库中的所有函数全都是由实用库中的所有函数全都是由OpenGL基本库函数基本库函数来编写的,所以,在使用上和来编写的,所以,在使用上和OpenGL基本库的使基本库的使用是完全相同的,而且,用户也可以使用基本函用是完全相同的,而且,用户也可以使用基本函数库来实现实用库的函数功能。数库来实现实用库的函数功能。OpenGL的辅助库是为了方便用户用标准的辅助库是为了方便用户用标准C编写编写OpenGL程序而编写的。程序而编写的。OpenGL是一个图形标准,所以,在是一个图形标准
11、,所以,在OpenGL中没有提供窗口管理和消息事件响应的函数,中没有提供窗口管理和消息事件响应的函数,这样使用标准这样使用标准C 编写编写OpenGL程序是很不方便的,所以程序是很不方便的,所以提供了辅助库。提供了辅助库。它提供了它提供了31个函数,这些函数都是以个函数,这些函数都是以“aux”为前缀。为前缀。OpenGL辅助库提供了一些基本的窗口辅助库提供了一些基本的窗口管理函数、事件处理函数和一些简单模型的制作函数等,管理函数、事件处理函数和一些简单模型的制作函数等,例如,定义窗口的大小、处理键盘时间、鼠标击键事件、例如,定义窗口的大小、处理键盘时间、鼠标击键事件、绘制多面体等等。绘制多面
12、体等等。10.2.2 一个简单的一个简单的OpenGL程序程序下面将通过一个简单的下面将通过一个简单的OpenGL 程序来说明程序来说明OpenGL头文头文件的使用、语法规则、程序的基本结构、程序的运行环件的使用、语法规则、程序的基本结构、程序的运行环境配置。境配置。例例10.1 OpenGL 例程例程 sample.c#include#include#include#include#include void myinit(void);void CALLBACK myReshape(int w,int h);void CALLBACK display(void);void myinit(voi
13、d)/初始化初始化glClearColor(0.0,0.0,0.0,0.0);/将窗口清为黑色将窗口清为黑色void CALLBACK display(void)glClear(GL_COLOR_BUFFER_BIT);/将颜色缓存清为将颜色缓存清为glClearColor命令所设置的颜色,即背景色命令所设置的颜色,即背景色glColor4f(0.2,0.8,1.0,1.0);/选颜色选颜色(R,G,B)glRotatef(30,1.0,1.0,0.0);/做旋转变换做旋转变换auxWireCube(1.0);/绘制六面体的虚线图绘制六面体的虚线图glFlush();/强制绘图,不驻留缓存强制
14、绘图,不驻留缓存 void CALLBACK myReshape(int w,int h)/用于窗口大小改变时的处理,用于窗口大小改变时的处理,与绘图无关与绘图无关glViewport(0,0,w,h);void main(void)auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);/窗口显示单缓存和窗口显示单缓存和RGB(彩色彩色)模式模式auxInitPosition(0,0,200,200);/大小大小 x=200 y=200 (0,0)是屏幕左上点是屏幕左上点auxInitWindow(“openglsample.c”);/初始化窗口,参数是标题初始化窗口
15、,参数是标题myinit();auxReshapeFunc(myReshape);auxMainLoop(display);1.头文件使用头文件使用若应用程序使用若应用程序使用OpenGL核心函数,应包括头文核心函数,应包括头文件件;使用使用GLU库函数,应包括头文件库函数,应包括头文件;使用使用AUX库函数,应包括头文件库函数,应包括头文件;使用使用WGL和和Win32应包括头文件应包括头文件。2.回调(回调(CALLBACK)函数)函数CALLBACK函数是一些用来让系统调用的函数,函数是一些用来让系统调用的函数,系统调用它们来实现显示、接受输入事件功能。系统调用它们来实现显示、接受输入事
16、件功能。3.语法规则语法规则OpenGL基本库的所有操作函数都是以基本库的所有操作函数都是以“gl”为前缀的。为前缀的。实用库的所有操作函数都是以实用库的所有操作函数都是以“glu”为前缀。辅助库的为前缀。辅助库的所有操作函数都是以所有操作函数都是以“aux”为前缀的。为前缀的。OpenGL命令带命令带有后缀。有后缀。以以sample.c中的中的glColor4f为例,前缀为例,前缀“gl”指这个函数是指这个函数是OpenGL的核心库函数,组成命令的单词首字母大写,的核心库函数,组成命令的单词首字母大写,如如“Color”;后缀;后缀“4”表示颜色值是由表示颜色值是由4个变量来表示个变量来表示
17、的;的;“f”表示所表示颜色的每个分量的类型为表示所表示颜色的每个分量的类型为32位浮点位浮点数。数。OpenGL核心库函数常量是以核心库函数常量是以“GL_”开头,均用大写开头,均用大写字母,并用下划线将每个关键词分开,如字母,并用下划线将每个关键词分开,如GL_COLOR_BUFFER_BIT。4.程序的基本结构程序的基本结构 一个一个OpenGL程序的基本结构是很简单的,无论多么复杂程序的基本结构是很简单的,无论多么复杂的的OpenGL程序,可以大致分解成以下部分:程序,可以大致分解成以下部分:(1)定义窗口)定义窗口Windows 系统下的系统下的OpenGL实现提供了一个辅助函数库实
18、现提供了一个辅助函数库aux,用于解决开窗口和处理输入事件等问题。用于解决开窗口和处理输入事件等问题。窗口管理函数:窗口管理函数:首先,调用首先,调用void auxInitDisplayMode(Glbitfield mask)函函数定义窗口的特性,如颜色和缓存区的性质。例如:数定义窗口的特性,如颜色和缓存区的性质。例如:auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);/窗口显示单缓存和窗口显示单缓存和RGB(彩色彩色)模式模式其次,调用其次,调用void auxInitPosition(Glint x,Glint y,Glint width,Glint he
19、ight)定义窗口在屏幕上的位置和大小。其定义窗口在屏幕上的位置和大小。其中,中,x,y为窗口左上角的坐标,为窗口左上角的坐标,width,height 分别为窗口的分别为窗口的宽和高宽和高(像素个数像素个数)。默认值为。默认值为(0,0,100,100)。例如:。例如:auxInitPosition(0,0,200,200);/大小大小 x=200 y=200 (0,0)是屏幕左上点是屏幕左上点最后,完成上述两个函数调用后,用函数最后,完成上述两个函数调用后,用函数void auxInitWindow(Glbyte*titleString)打开窗口。窗口的标打开窗口。窗口的标题为字符串题为字
20、符串titleString。窗口把。窗口把ESC键与退出函数联系起键与退出函数联系起来,可以用来关闭窗口,退出程序。例如:来,可以用来关闭窗口,退出程序。例如:auxInitWindow(“openglsample.c”);/初始化窗口,参数是标题初始化窗口,参数是标题处理输入事件处理输入事件:当改变窗口尺寸、移动窗口、重新显示窗口时,当改变窗口尺寸、移动窗口、重新显示窗口时,由由auxReshapeFunc(myReshape)调用函数调用函数myReshape重新定义窗口属性。重新定义窗口属性。通常通常myReshape函数调用函数调用glViewPort函数,对当函数,对当前图形进行裁剪
21、,重新定义投影矩阵等。前图形进行裁剪,重新定义投影矩阵等。OpenGL辅助函数库中还包括处理键盘和鼠标输辅助函数库中还包括处理键盘和鼠标输入事件的函数。入事件的函数。(2)初始化操作)初始化操作由于由于OpenGL的绘图方式是由一系列的状态确定的,因而在绘的绘图方式是由一系列的状态确定的,因而在绘制图形前需要做一些准备工作,包括制图形前需要做一些准备工作,包括清缓存区(清缓存区(buffer)、定)、定义光照模型、定义纹理映射等基本操作的初始化状态、设置义光照模型、定义纹理映射等基本操作的初始化状态、设置三维视景体、定义视口。三维视景体、定义视口。例如:例如:glClearColor(0.0,
22、0.0,0.0,0.0);/将窗口清为黑色将窗口清为黑色glClear(GL_COLOR_BUFFER_BIT);/将颜色缓存清为将颜色缓存清为glClearColor命令所设置的颜色,即背景色命令所设置的颜色,即背景色(3)设置观察坐标系下的取景模式和取景框位置及大小设置观察坐标系下的取景模式和取景框位置及大小主要利用了三个函数:主要利用了三个函数:函数函数void glViewport(GLint x,Glint y,Glsizei width,Glsizei height):设置在屏幕上的视口大小,四个参数描述:设置在屏幕上的视口大小,四个参数描述屏幕视口四个角上的坐标(以像素表示)。屏
23、幕视口四个角上的坐标(以像素表示)。参数参数(x,y)用于指定视口的左下角在窗口坐标系中的位置,用于指定视口的左下角在窗口坐标系中的位置,参数参数width和和height分别确定矩形视口的宽和高,均以像素分别确定矩形视口的宽和高,均以像素为单位为单位。注意:视口的大小和尺寸是在窗口坐标系中进行度量的,注意:视口的大小和尺寸是在窗口坐标系中进行度量的,默认状态下其坐标原点位于窗口的左下角,其尺寸与窗口默认状态下其坐标原点位于窗口的左下角,其尺寸与窗口的大小相同。的大小相同。视点方向观察体积 函数函数void glOrtho(left,right,bottom,top,near,far):设置投
24、影方式为正交投影(平行投影),其取景体积设置投影方式为正交投影(平行投影),其取景体积是一个各面均为矩形的六面体是一个各面均为矩形的六面体。函数函数void gluPerspective(fovy,aspect,zNear,zFar):设置:设置投影方式为透视投影,其取景体积是一个截头锥体,在投影方式为透视投影,其取景体积是一个截头锥体,在这个体积内的物体投影到锥的顶点。这个体积内的物体投影到锥的顶点。它通过指定它通过指定x-z平面内的视角大小及宽高比来确平面内的视角大小及宽高比来确定沿视线方向的棱锥,并通过指定远、近剪切面定沿视线方向的棱锥,并通过指定远、近剪切面与视点间的距离来截断棱锥,得
25、到观察体。与视点间的距离来截断棱锥,得到观察体。注注:在默认状态下投影方式为平行正交投影。在默认状态下投影方式为平行正交投影。(4)使用使用OpenGL的库函数构造几何物体对象的的库函数构造几何物体对象的数学描述。包括点线面的位置和拓扑关系、几何数学描述。包括点线面的位置和拓扑关系、几何变换、光照处理等。这是变换、光照处理等。这是OpenGL程序的主要部分。程序的主要部分。在例在例10.1中,在函数中,在函数void CALLBACK display(void)中写好中写好要绘制的三维图形要绘制的三维图形,然后,在主程序中,然后,在主程序中调用调用auxMainLoop(display)就可让
26、该就可让该图形一直显示。图形一直显示。(5)程序的微机运行环境配置)程序的微机运行环境配置 软件与硬件环境软件与硬件环境 操作系统:操作系统:Windows 95/98,Windows NT 软件开发环境:软件开发环境:Microsoft Visual C+4.0及以上版本及以上版本 硬件:奔腾级微机,最好配有支持硬件:奔腾级微机,最好配有支持OpenGL硬加速的图形卡硬加速的图形卡 连接三个静态库连接三个静态库 程序中除了包含必需的头文件如程序中除了包含必需的头文件如 外,外,在创建执行文件时,在在创建执行文件时,在VC环环境设置中要连接境设置中要连接opengl32.lib,glu32.l
27、ib和和glaux.lib 三个函数库。运三个函数库。运行已创建的执行文件时,在行已创建的执行文件时,在windowssystem目录下要有目录下要有opengl32.dll,glu32.dll两个动态连接库。两个动态连接库。10.3 OpenGL程序设计入门程序设计入门 OpenGL的状态机制的状态机制 OpenGL中的图元绘制中的图元绘制 坐标变换及其坐标变换及其OpenGL实现实现 应用变换的一个实例应用变换的一个实例 光照处理光照处理10.3.1 OpenGL的状态机制的状态机制OpenGL的绘图方式是由一系列的状态决定的,如果设置了的绘图方式是由一系列的状态决定的,如果设置了一种状态
28、或模式而不改变它,一种状态或模式而不改变它,OpenGL在绘图过程中将一直在绘图过程中将一直保持这种状态或模式。保持这种状态或模式。例如,当前绘图颜色就是例如,当前绘图颜色就是OpenGL 的一个状态,当选定颜的一个状态,当选定颜色后,色后,OpenGL就用这个颜色绘图。在例就用这个颜色绘图。在例10.1中,以下语句中,以下语句void myinit(void)glClearColor(0.0,0.0,0.0,0.0);中的函数中的函数glClearColor(0.0,0.0,0.0,0.0)将视口背景色清为黑将视口背景色清为黑色,如果不改变这种状态,视口背景色将一直保持为黑色。色,如果不改变
29、这种状态,视口背景色将一直保持为黑色。再如:再如:glColor3f(1.0,0.0,0.0);/设置当前颜色为红色设置当前颜色为红色glColor3f(0.0,0.0,1.0);/设置当前颜色为蓝色设置当前颜色为蓝色glRectf(0.5,0.5,0.7,0.7);/绘制一个矩形绘制一个矩形glColor3f(0.0,1.0,0.0);/设置当前颜色为绿色设置当前颜色为绿色glRectf(0.8,0.8,0.9,0.9);glRectf(0.2,0.2,0.4,0.4);执行结果是:一个蓝色的矩形和两个绿色的矩形。执行结果是:一个蓝色的矩形和两个绿色的矩形。10.3.2 OpenGL中的图元
30、绘制中的图元绘制 任何复杂的图形都是由基本的图元点、线和多边形任何复杂的图形都是由基本的图元点、线和多边形组成的。组成的。程序格式如下:程序格式如下:要绘制某个几何对象,首先必须指明究竟是哪种类要绘制某个几何对象,首先必须指明究竟是哪种类型的几何对象(例如点、线和多边形),否则系统型的几何对象(例如点、线和多边形),否则系统在执行绘图操作时无法判断究竟是画什么。在执行绘图操作时无法判断究竟是画什么。OpenGL提供了一对用于指定顶点序列操作的函数,确定基提供了一对用于指定顶点序列操作的函数,确定基本几何对象的类型。本几何对象的类型。glBegin(););/描述一组顶点,用于建构某种几何对象描
31、述一组顶点,用于建构某种几何对象glEnd();();1.点的绘制点的绘制 OpenGL中点定义为一个方块,在默认状态下,点是中点定义为一个方块,在默认状态下,点是屏幕上的一个像素。在屏幕上的一个像素。在OpenGL中,一个点是当作一中,一个点是当作一个个 n(2,3,4)维向量来处理的。)维向量来处理的。OpenGL 中的点是三维的,如果用户设定二维坐标中的点是三维的,如果用户设定二维坐标(x,y),则,则OpenGL在实际计算时处理的点为(在实际计算时处理的点为(x,y,0););对于由四维齐次坐标定义的顶点(对于由四维齐次坐标定义的顶点(x,y,z,w),在在w非零非零时,齐次顶点(时,
32、齐次顶点(x,y,z,w)对应于三维坐标中的点)对应于三维坐标中的点(x/w,y/w,z/w);若);若w=0.0,则对应于无穷远处的点。,则对应于无穷远处的点。glVertex 2,3,4dfisv(TYPE coords);例如:例如:glVertex2i(0,1);glVertex3d(-1.0,1.0,3.1425926);glVertex4d(40,-15.9,0,2);Glfloat v3=-1.2f,3.4f,5.6f;glVertex3fv(v);以下操作的结果是在屏幕上绘制三个点以下操作的结果是在屏幕上绘制三个点:glBegin(GL_POINTS)glVertex3f(1.
33、0,0.0,0.0);glVertex3f(1.0,1.0,0.0);glVertex3f(0.0,1.0,1.0);glEnd();2.线的绘制线的绘制与数学意义上两端无限延伸的直线不同,与数学意义上两端无限延伸的直线不同,OpenGL的线是的线是数学定义中的线段,用成对的端点来描述。如:数学定义中的线段,用成对的端点来描述。如:glBegin(GL_LINES)glVertex2f(0.0,0.0);glVertex2f(1.0,1.0);glEnd();上述操作描述了一条由坐标原点到点(上述操作描述了一条由坐标原点到点(1.0,1.0)的线段。)的线段。3.多边形的绘制多边形的绘制多边形
34、指封闭线段围成的区域。但多边形指封闭线段围成的区域。但OpenGL中可以描述的中可以描述的多边形有两点限制:多边形的边除了多边形的顶点外不允多边形有两点限制:多边形的边除了多边形的顶点外不允许相交,即确保多边形为简单多边形;多边形为凸多边形,许相交,即确保多边形为简单多边形;多边形为凸多边形,即任给多边形的两个内部点,其连线完全在多边形内。即任给多边形的两个内部点,其连线完全在多边形内。多边形的描述方式如下:多边形的描述方式如下:glBegin(GL_POLYGON);glVertex*(v0);glVertex*(v1);.glVertex*(vn);glEnd();其中,其中,*表示表示g
35、lVertex函数的上述任一种组合形式,由多边函数的上述任一种组合形式,由多边形顶点形顶点v0,v1,vn的表示形式而定。的表示形式而定。注意:多边形顶点应按一定顺序排列(如逆时针)。注意:多边形顶点应按一定顺序排列(如逆时针)。4.矩形的绘制矩形的绘制由于矩形在几何体构造中出现得比较频繁,所以由于矩形在几何体构造中出现得比较频繁,所以OpenGL提提供了专门的矩形函数:供了专门的矩形函数:void glRectdfis(TYPE x1,TYPE y1,TYPE x2,TYPE y2);void glRectdfisv(TYPE*v1,TYPE*v2);矩阵的左上、右下角点坐标分别为(矩阵的左
36、上、右下角点坐标分别为(x1,y1)和)和(x2,y2),或,或者用数组指针者用数组指针v1、v2表示。用上述函数描述的矩形位于表示。用上述函数描述的矩形位于z=0平面内,并且各边分别平行于平面内,并且各边分别平行于x、y轴。但注意:经过坐标轴。但注意:经过坐标变换之后,这些特性可能改变。变换之后,这些特性可能改变。例例10.2 基本的图元绘制程序基本的图元绘制程序 为简单起见,我们仅改变例为简单起见,我们仅改变例10.1中的绘制函数中的绘制函数void CALLBACK display(void)如下:如下:void CALLBACK display(void)glClear(GL_COLO
37、R_BUFFER_BIT);/将颜色缓存清为将颜色缓存清为glClearColor命令所设置的颜色,即背景色命令所设置的颜色,即背景色 glColor4f(1.0,1.0,1.0,1.0);/选颜色选颜色(R,G,B)glPointSize(6.0);/设置点的大小设置点的大小glBegin(GL_POINTS);/在屏幕上绘制三个点在屏幕上绘制三个点 glVertex3f(0.1,0.2,0.0);glVertex3f(0.2,0.7,0.0);glVertex3f(0.5,0.8,0.0);glEnd();glBegin(GL_LINES);/在屏幕上绘制一条线段在屏幕上绘制一条线段 gl
38、Vertex2f(0.0,0.4);glVertex2f(-0.3,0.8);glEnd();glBegin(GL_POLYGON);/在屏幕上绘制一个四边形在屏幕上绘制一个四边形 glVertex2f(-0.6,0.0);glVertex2f(-0.4,0.0);glVertex2f(-0.4,0.3);glVertex2f(-0.6,0.4);glEnd();glColor3f(1.0,0.0,0.0);/设置当前颜色为红色设置当前颜色为红色 glColor3f(0.0,0.0,1.0);/设置当前颜色为蓝色设置当前颜色为蓝色 glRectf(0.5,0.5,0.7,0.7);/绘制一个矩
39、形绘制一个矩形 glColor3f(0.0,1.0,0.0);/设置当前颜色为绿色设置当前颜色为绿色 glRectf(0.8,0.8,0.9,0.9);/绘制一个矩形绘制一个矩形 glRectf(0.2,0.2,0.4,0.4);/绘制一个矩形绘制一个矩形 glFlush();/强制绘图,不驻留缓存强制绘图,不驻留缓存 用该函数替换例用该函数替换例10.1中相应的函数后,运行的结果如下中相应的函数后,运行的结果如下图所示。图所示。10.3.3 坐标变换及其坐标变换及其OpenGL实现实现在二维平面上创建三维物体的过程:在二维平面上创建三维物体的过程:在三维空间中创建所绘制物体的模型,由计算机经
40、过适当的在三维空间中创建所绘制物体的模型,由计算机经过适当的变换,将三维坐标系中的点转换为屏幕上的相应位置,以得变换,将三维坐标系中的点转换为屏幕上的相应位置,以得到理想的视觉效果。到理想的视觉效果。OpenGL就是实现将物体的各个顶点通过各种变换矩阵的作就是实现将物体的各个顶点通过各种变换矩阵的作用映射到屏幕的过程用映射到屏幕的过程。下图是顶点变换过程。注意:。下图是顶点变换过程。注意:在模在模式观察变换过程中,顶点的法向量也自动地进行变换。式观察变换过程中,顶点的法向量也自动地进行变换。在在OpenGL编程过程中编程过程中,程序员必须在头脑中有整个坐标程序员必须在头脑中有整个坐标变换过程的
41、清晰的图像,才能将所建的场景模型正确地变换过程的清晰的图像,才能将所建的场景模型正确地显示在屏幕上。显示在屏幕上。OpenGL的坐标变换过程类似于用照相机拍摄照片的坐标变换过程类似于用照相机拍摄照片的过程。使用照相机与坐标变换的步骤比较如下:的过程。使用照相机与坐标变换的步骤比较如下:(1)竖起三角架,将照相机对准场景(视图变换竖起三角架,将照相机对准场景(视图变换,取取景变换景变换,视点变换)。视点变换)。(2)将要拍的场景置于所要求的位置上(造型变将要拍的场景置于所要求的位置上(造型变换)。换)。(3)选择照相机透镜或调整焦距(投影变换)。选择照相机透镜或调整焦距(投影变换)。(4)确定最
42、终的照片需要多大,例如放大照片(视确定最终的照片需要多大,例如放大照片(视口变换)。口变换)。其中其中(1)、(2)顺序可看成照相馆中的照相过程;而顺序可看成照相馆中的照相过程;而在室外摄影时,由于先有景物,再选择照相机的位在室外摄影时,由于先有景物,再选择照相机的位置与方向,因此照相顺序可看成置与方向,因此照相顺序可看成(2)、(1)。OpenGL中的多种变换(几何变换、投影变换等)是由矩中的多种变换(几何变换、投影变换等)是由矩阵的乘积实现的。阵的乘积实现的。OpenGL提供了一系列矩阵操作函数。提供了一系列矩阵操作函数。(1)通用的矩阵操作命令通用的矩阵操作命令void glMatrix
43、Mode(Glenum mode);参数取值:参数取值:GL_MODELVIEW、GL_PROJECTION或或GL_TEXTURE。默认的选定默认的选定矩阵为造型矩阵为造型-观察变换矩阵。观察变换矩阵。void glLoadIdentity(void);OpenGL中的变换命令都是对当前矩阵(当前矩阵为中的变换命令都是对当前矩阵(当前矩阵为以后图形变换所要使用的矩阵)进行操作,因此在以后图形变换所要使用的矩阵)进行操作,因此在选定可修改矩阵后,应首先用上述命令设置当前操选定可修改矩阵后,应首先用上述命令设置当前操作矩阵为单位矩阵。作矩阵为单位矩阵。(2)造型)造型-观察变换观察变换 造型造型
44、-观察变换过程就是一个将顶点坐标从世界坐标变观察变换过程就是一个将顶点坐标从世界坐标变换到视觉坐标的过程。这里很重要的是对两个坐标系的认换到视觉坐标的过程。这里很重要的是对两个坐标系的认识。识。世界坐标系也称为全局坐标系。它是一个右手坐标系,世界坐标系也称为全局坐标系。它是一个右手坐标系,可以认为该坐标系是固定不变的,在初始态下,其可以认为该坐标系是固定不变的,在初始态下,其x x轴为轴为沿屏幕水平向右,沿屏幕水平向右,y y轴为沿屏幕垂直向上,轴为沿屏幕垂直向上,z z轴则为垂直屏轴则为垂直屏幕面向外指向用户。幕面向外指向用户。视觉坐标系视觉坐标系(即观察坐标系即观察坐标系)也称为局部坐标系
45、。它是也称为局部坐标系。它是一个左手坐标系,该坐标系是可以活动的。在初始态下,一个左手坐标系,该坐标系是可以活动的。在初始态下,其原点及其原点及x x、y y轴分别与世界坐标系的原点及轴分别与世界坐标系的原点及x x、y y轴重合,轴重合,而而z z轴则正好相反,即为垂直屏幕面向内。轴则正好相反,即为垂直屏幕面向内。在初始状态下在初始状态下,相机在观察坐标系的原点且指向相机在观察坐标系的原点且指向z z轴正轴正向向,即为垂直屏幕面向内。即为垂直屏幕面向内。平移变换平移变换 void glTanslatefd(TYPE x,TYPE y,TYPE z);旋转变换旋转变换void glRotate
46、fd(TYPE angle,TYPE x,TYPE y,TYPE z);绕矢量绕矢量v=(x,y,z)T逆时针方向旋转逆时针方向旋转angle指定的角度。旋转角指定的角度。旋转角度的范围是度的范围是0360度。当度。当angle=0时,时,glRotate()不起作用。不起作用。缩放变换缩放变换 void glScalefd(TYPE x,TYPE y,TYPE z);变换的顺序:变换的顺序:glMatrixMode(GL_MODELVIEW);glLoadIdentity();glMultMatrixf(N);/*apply transformation N*/glMultMatrixf(M
47、);/*apply transformation M*/glMultMatrixf(L);/*apply transformation L*/glBegin(GL_POINTS);glVertex3f(v);/*draw transformed vertex v*/glEnd();在这个过程中,在在这个过程中,在GL_MODELVIEW状态下,相继引入状态下,相继引入了了I(单位阵)(单位阵),N,M,L矩阵。变换后的顶点为矩阵。变换后的顶点为NMLv(顶点取列顶点取列向量向量)。因此,顶点的变换为。因此,顶点的变换为N(M(Lv),即是先作变换,即是先作变换L,然后,然后是变换是变换M,最后
48、才是最后才是N。这里,顶点。这里,顶点v 的实际变换顺序正好与的实际变换顺序正好与指定的顺序相反。指定的顺序相反。(3)投影变换)投影变换在调用投影变换命令前必须先在程序中加入下述语在调用投影变换命令前必须先在程序中加入下述语句:句:glMatrixMode(GL_PROJECTION);glLoadIdentity();这两条命令一方面指定接下来的变换命令只影响投这两条命令一方面指定接下来的变换命令只影响投影矩阵,同时也将当前投影矩阵设置为单位阵。影矩阵,同时也将当前投影矩阵设置为单位阵。透视投影透视投影void gluPerspective(Gldouble fovy,Gldouble a
49、spect,Gldouble zNear,Gldouble zFar);正交投影正交投影 void glOrtho(Gldouble left,Gldouble right,Gldouble bottom,Gldouble top,Gldouble near,Gldouble far);对于二维图形向二维屏幕的投影,则应使用实用库中的如对于二维图形向二维屏幕的投影,则应使用实用库中的如下函数:下函数:void gluOrtho2D(Gldouble left,Gldouble right,Gldouble bottom,Gldouble top);前面提到过,用二维顶点命令绘制的二维物体的前面
50、提到过,用二维顶点命令绘制的二维物体的z坐标均为坐标均为零,而零,而gluOrtho2D()命令假定场景中的命令假定场景中的 z 坐标介于坐标介于-1.0和和 1.0 之间。之间。(4)视口变换视口变换 void glViewport(GLint x,Glint y,Glsizei width,Glsizei height);窗口和视口是两个不同的概念窗口和视口是两个不同的概念。注意:应该使视口的长宽比与取景体积的长宽比相等,注意:应该使视口的长宽比与取景体积的长宽比相等,否则会使图像变形。否则会使图像变形。10.3.4 应用变换的一个实例应用变换的一个实例本节将通过一个简单的程序进一步阐述本