《OpenGL基础操作篇.docx》由会员分享,可在线阅读,更多相关《OpenGL基础操作篇.docx(8页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第一章 OpenGL 基本程序结构用OpenGL编写的程序结构类似于用其他语言编写的程序。实际上,OpenGL是一个丰富的三维图形函数库,编写OpenGL程序并非难事,只需在基本C语言中调用这些函数,用法同Turbo C、Microsoft C等类似,但也有许多不同之处。本书所有的程序都是在Windows NT的Microsoft Visual C+ 2.0 集成环境下编译连接的,其中有部分头文件和函数是为这个环境所用的,如头文件glos.h。此外,为便于各类读者同时快速入门,在短时间内掌握OpenGL编程的基本方法和技巧,书中例子尽量采用标准ANSI C调用OpenGL函数来编写,而且所有例
2、程都只采用OpenGL附带的辅助库中的窗口系统。此外,这样也便于程序在各平台间移植,尤其往工作站UNIX操作系统移植时,也只需改动头文件等很少很少的部分。 下面列出一个简单的OpenGL程序simple.c:例 2-1 OpenGL简单例程 simple.c #include #include #include glos.h void main(void) auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,500,500); auxInitWindow(simple); glClearColor(0.0,0.0,0.0,0
3、.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0,0.0,0.0); glRectf(-0.5,-0.5,0.5,0.5); glFlush(); _sleep(1000); 这个程序运行结果是在屏幕窗口内画一个红色的方块。下面具体分析整个程序结构:首先,在程序最开始处是OpenGL头文件:、。前一个是gl库的头文件,后一个是辅助库的头文件。此外,在以后的几章中还将说明OpenGL的另外两个头文件,一个是实用库的头文件,另一个是X窗口扩充库的头文件(这个常用在工作站上)。接下来是主函数main()的定义: 一般的程序结构是先定义一个窗口, aux
4、InitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,500,500); auxInitWindow(simple);auxInitDisplayMode(AUX_SINGLE|AUX_RGBA)设置窗口显示模式为RGBA方式,即彩色方式,并且图形缓存为单缓存(SINGLE BUFFER)。auxInitPosition(0,0,500,500)定义窗口的初始位置,前两个参数(0,0)为窗口的左上角点的屏幕坐标,后两个参数(500,500)为窗口的宽度和高度。auxInitWindow(simple)是窗口初始化,字符参数是窗口名称
5、。 然后是窗口内清屏, glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT);第一句将窗口清为黑色,第二句将颜色缓冲区清为glClearColor(0.0,0.0,0.0,0.0)命令所设置的颜色,即同窗口背景颜色一致。 再接着是在窗口内画一个物体, glColor3f(1.0,0.0,0.0); glRectf(-0.5,-0.5,0.5,0.5);很明显,第一句设置物体颜色,函数中前三个参数分别为R、G、B值,最后一个参数是Alpha值,范围都从0至1;第二句绘制一个二维矩形。注意,OpenGL是针对三维图形而言,因此用作O
6、penGL编程绘制物体必须意识到任何一个物体都是三维的,具有空间性,而显示于屏幕上的物体都是三维物体在二维平面上的投影。从表面上看,上述程序代码很简单,实际上已经用到了缺省的投影形式(正射投影)。 再看glFlush()函数,表示强制绘图完成。最后一句_sleep(1000),参数单位为毫秒,整句意思是保持现有状况一秒钟,然后结束程序运行。这个函数是VC的库函数。总之,OpenGL程序基本结构为定义窗口、清理窗口、绘制物体、结束运行。第二章 OpenGL数据类型和函数名OpenGL的数据类型定义可以与其它语言一致,但建议在ANSI C下最好使用以下定义的据类型,如GLint、GLfloat等。
7、具体类型见表2-2-1._前缀 数据类型 相应C语言类型 OpenGL类型_ b 8-bit integer signed char GLbyte s 16-bit integer short GLshort i 32-bit integer long GLint,GLsizei f 32-bit floating-point float GLfloat,GLclampf d 64-bit floating-point double GLdouble,GLclampd ub 8-bit unsigned integer unsigned char GLubyte,GLboolean us 16
8、-bit unsigned integer unsigned short GLushort ui 32-bit unsigned integer unsigned long GLuint,GLenum,GLbitfield_ 表 2-2-1 命令前缀和参数数据类型OpenGL的库函数命名方式很有规律,了解这种规律后阅读和编写程序都比较容易方便。首先,每个库函数有前缀 gl、glu、glx或aux,表示此函数分属于基本库、实用库、X 窗口扩充库或辅助库,其后的函数名头字母大写,后缀是参数类型的简写,取i、f,参见表2-1。例: glVertex2i(2,4); glVertex3f(2.0,4.
9、0,5.0);注意,有的函数参数类型后缀前带有数字2、3、4。2代表二维,3代表三维,4代表alpha值(以后详细介绍)。有些OpenGL函数最后带一个字母v,表示函数参数可用一个指针指向一个向量(或数组)来替代一系列单个参数值。下面两种格式都表示设置当前颜色为红色,二者等价。 glColor3f(1.0,0.0,0.0); float color_array=1.0,0.0,0.0; glColor3fv(color_array);除了以上基本命名方式外,还有一种带“*”星号的表示方法,如glColor*(),它表示可以用函数的各种方式来设置当前颜色。同理,glVertex*v()表示用一个
10、指针指向所有类型的向量来定义一系列顶点坐标值。最后,OpenGL也定义GLvoid类型,如果用C语言编写,可以用它替代void类型。第三章 OpenGL辅助库的基本使用OpenGL是一个开放的系统,它是独立于任何窗口系统或操作系统的。尽管它包含了许多图形函数,但它却没有窗口函数,也没有从键盘和鼠标读取事件的函数,所以要初学者写出一个完整的图形程序是相当困难的。另外,OpenGL图形函数中只提供基本的几何原形:点、线、多边形,因此要创建基本的三维几何体如球、锥体等,也很不容易。而OpenGL辅助库就是为解决这些基本问题专门设计的,它提供了一些基本的窗口管理函数和三维图形绘制函数,能帮助初学者尽快
11、进入OpenGL世界,掌握关键的三维图形技术,体会其中奇妙的乐趣。但是,对于复杂的应用,这些函数远远不够,只能作为参考。3.1 辅助库函数分类 这一节内容可以作为手册查阅,初学者不必深究。 辅助库函数大致分为六类: 1.窗口初始化和退出。相关函数有三个,它们在第一章已提到,这里将详细介绍:void auxInitWindow(GLbyte *titleString)打开一个由auxInitDisplayMode()和auxInitPosition()指定的窗口。函数参数是窗口标题,窗口背景缺省颜色是RGBA下的黑色或颜色表(color_index)下的0号调色板的颜色。按下Escape键可以完
12、成关掉窗口、结束程序、全部清屏三项功能。void auxInitDisplayMode(GLbitfield mask)设置窗口显示模式。基本模式有RGBA或颜色表、单或双缓存,也可指定其他附加模式:深度、模板或累积缓存(depth,stencil,and/or accumulation buffer)。参数mask是一组位标志的联合(取或),AUX_RGBA或AUX_INDEX、AUX_SINGLE或AUX_DOUBLE,以及其它有效标志AUX_DEPTH、AUX_STENCIL或AUX_ACCUM。void auxInitPosition(GLint x,GLint y,GLsizei w
13、idth,GLsizei height)设置窗口位置及大小。参数(x,y)为窗口的左上角点的屏幕坐标,参数(width,height)为窗口的宽度和高度,单位为象素,缺省值为(0,0,100,100)。2.窗口处理和事件输入。当窗口创建后,且在进入主函数循环之前,应当登记以下列出的回调函数(callback function):void auxReshapeFunc(void(*function)(GLsizei,GLsizei)定义窗口改变时形状重定函数。参数function是一个函数指针,这个函数带有两个参数,即窗口改变后的新宽度和新高度。通常,function是glViewport(),
14、显示裁减后的新尺寸,重定义投影矩阵,以便使投影后图像的比例与视点匹配,避免比例失调。若不调用auxReshapeFunc(),缺省重定物体形状的函数功能是调用一个二维的正射投影矩阵。运用辅助库,窗口将在每个事件改变后自动重新绘制。void auxKeyFunction(GLint key,void(*function)(void)定义键盘响应函数。参数function就是当按下 key 键时所调用的函数指针,辅助库为参数key定义了几个常量:AUX_0至AUX_9、AUX_A至AUX_Z、AUX_a至AUX_z、AUX_LEFT、AUX_RIGHT、AUX_UP、AUX_DOWN(方向键)、A
15、UX_ESCAPE、AUX_SPACE或AUX_RETURN。void auxMouseFunc(GLint button,Glint mode,void(*function)(AUX_EVENTREC *)定义鼠标响应函数。参数function就是当鼠标以mode方式作用于button时所调用的函数。参数button有AUX_LEFTBUTTON、AUX_MIDDLEBUTTON或AUX_RIGHTBUTTON(以右手为标准)。参数mode代表鼠标触击状态,击中时为AUX_MOUSEDOWN,释放时为AUX_MOUSEUP。参数function必须带一个参数,它是指向结构AUX_EVENNT
16、REC的指针。当函数auxMouseFunc()被调用时将为这个结构分配相应的内存。通常用法类似如下: void function(AUX_EVENTREC *event) GLint x,y; x=event-dataAUX_MOUSEX; y=event-dataAUX_MOUSEY; . 3.颜色表装入。因为OpenGL本身没有窗口系统,所以依赖于窗口系统的颜色映射就没法装入颜色查找表。如果采用颜色表模式,就要用到辅助库提供的用RGB值定义的单个颜色索引函数:void auxSetOneColor(GLint index,GLfloat red,GLfloat green,GLfloat
17、 blue)设置自定义颜色的索引。参数index即索引号,参数red、green、blue分别为红、绿、蓝值,范围在(0,1)内。 4.三维物体绘制。每组三维物体包括两种形式:网状体(wire)和实心体(solid)。网状体没有平面法向,而实心体有,能进行光影计算,有光照时采用实心体模型。下面这些函数的参数都是定义物体大小的,可以改变。void auxWireSphere(GLdouble radius)void auxSolidSphere(GLdouble radius) 绘制球。void auxWireCube(GLdouble size)void auxSolidCube(GLdoub
18、le size) 绘制立方体。void auxWireBox(GLdouble width,GLdouble height,GLdouble depth)void auxSolidBox(GLdouble width,GLdouble height,GLdouble depth) 绘制长方体。void auxWireTorus(GLdouble innerRadius,GLdouble outerRadius)void auxSolidTorus(GLdouble innerRadius,GLdouble outerRadius) 绘制环形圆纹面。void auxWireCylinder(GL
19、double radius,GLdouble height)void auxSolidCylinder(GLdouble radius,GLdouble height) 绘制圆柱。void auxWireIcosahedron(GLdouble radius)void auxSolidIcosahedron(GLdouble radius) 绘制二十面体。void auxWireOctahedron(GLdouble radius)void auxSolidOctahedron(GLdouble radius) 绘制八面体。void auxWireTetrahedron(GLdouble ra
20、dius)void auxSolidTetrahedron(GLdouble radius) 绘制四面体。void auxWireDodecahedron(GLdouble radius)void auxSolidDodecahedron(GLdouble radius) 绘制十二面体。void auxWireCone(GLdouble radius,GLdouble height)void auxSolidCone(GLdouble radius,GLdouble height) 绘制圆锥。void auxWireTeapot(GLdouble size)void aucSolidTeapo
21、t(GLdouble size) 绘制茶壶。 以上物体均以各自中心为原点绘制,所有坐标都已单位化,可以缩放。 5.背景过程管理。void auxIdleFunc(void *func)定义空闲状态执行函数。参数func是一个指针,指向所要执行的函数功能。当它为零时,func执行无效。 6.程序运行。void auxMainLoop(void(*displayFunc)(void)定义场景绘制循环函数。displayFunc指针指向场景绘制函数。当窗口需要更新或场景发生改变时,程序便调用它所指的函数,重新绘制场景。3.2 辅助库应用示例 下面举一个辅助库的应用例子,testaux.c:例 2-2
22、 辅助库应用例程 testaux.c #include glos.h #include #include void myinit(void); void CALLBACK myReshape(GLsizei w,GLsizei h); void CALLBACK display(void); void myinit(void) glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); void CALLBACK myReshape(GLsizei w,GLsizei h) glViewport(0,0,w,h); glMatrix
23、Mode(GL_PROJECTION); glLoadIdentity(); if(w=h) glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0); else glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); void CALLBACK display(void) glColo
24、r3f(1.0,1.0,0.0); auxWireSphere(1.0); glFlush(); void main(void) auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,500,500); auxInitWindow(AUX_SAMPLE); myinit(); auxReshapeFunc(myReshape); auxMainLoop(display);图 2-3-1 网状球体以上程序运行结果是在屏幕窗口内绘制一个黄色的网状球体,这个程序充分体现了辅助库的基本应用方法。首先,在主函数中用辅助库函数定义一个窗口
25、auxInitWindow(),然后初始化颜色myinit(),这些在第一章中已说明。接下来是两个十分重要的函数auxReshapeFunc()和auxMainLoop(),参数都是一个函数指针,指向的都是回调函数(回调函数定义用CALLBACK说明)。前者是窗口形状重定函数,参数指针指向函数myReshape(),它的两个参数就是窗口的新宽度和新高度。然后用glViewport(0,0,w,h)重定视口,并且在新视口内重新定义投影矩阵, glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w=h) glOrtho(-1.5,1.5,-1.5*(
26、GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0); else glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0);即先用glMatrixMode()说明当前矩阵操作与投影有关GL_PROJECTION,再用glLoadIdentity() 将矩阵清为单位矩阵,避免受其它矩阵操作的干扰;然后调用glOrtho() 对物体进行正射投影,并且用判断语句给出了两种情况,使投影后图像的比例与视点匹配,避免比例失调。再下来调用glMatrixMode()将矩阵操作改为对观察物体有关的方式GL_MODELVIEW,同样用glLoadIdentity()清矩阵。后者是主函数循环函数,参数指针指向函数display(),即绘制物体。当窗口需要更新或物体发生改变时,程序便调用它重新绘制。 以上例子是辅助库的最基本应用,复杂的应用将在后续的章节中详细介绍。