开发基于OpenGL的应用程序,必须先了解OpenGL的库函数。它采用C语言风格,提供大量的函数来进行图形的处理和显示。OpenGL图形库一共有100多个函数,它们分别属于OpenGL的基本库、实用库、辅助库等不同的库。
OpenGL全称"开放式图形库",是由SGI公司开发的低层三维图形API,目前在图形开发领域已经成为工业标准。现今市面上关于OpenGL方面的书籍不在少数,但是大多是讲解句法和实例,缺乏对其整个程序开发框架的总结与把握,所以总体上显得比较凌乱。本篇文章主要针对初学者(最好要有图形方面的基础知识)而制作的,旨在通过对OpenGL的整个知识结构的介绍,来具体剖析其内在运行机制,并且结合实际开发经验总结出在VC平台下的OpenGL开发框架,最后给出一个例程来说明这一框架的具体应用。
一、OpenGL基础知识
OpenGL是一种开放式的图形软件开发包,它采用C语言风格,提供大量的函数来进行图形方面的处理,一般编程使用的函数库包括:
OpenGL图形库-----函数以gl开头,可以实现比较简单的绘制功能,核心函数共115个。这些函数可以运行在现在任何主流操作系统中。
OpenGL实用库-----函数以glu开头,其函数功能更高级一些,如绘制复杂的曲线曲面、高级坐标变换、多边形分割等,共有43个。这些函数可以运行在现在任何主流操作系统中。
OpenGL辅助库-----函数以aux开头,它们是一些特殊的函数,包括简单的窗口管理、输入事件处理、某些复杂三维物体绘制等函数,共有31个。它只能在Win32平台下运行。
OpenGL实用工具开发库----函数以glut开头,它们提供更为复杂的绘制功能,此函数由glut.dll来负责解释执行。
Windows专用函数库-----以wgl开头,负责OpenGL与Windows窗口系统的连接,共有6个。
Win32函数------无专用前缀,实际上为API函数,共5个,用来处理比如象素格式的选择及双缓冲等功能。
OpenGL提供的函数一般是以客户机/服务器的模式来运行的,即执行绘制图形功能的应用程序作为客户机,而OpenGL函数库(实际上是一些动态链接库,比如opengl32.dll,glu.dll等)作为服务器,当应用程序发出绘制请求时,服务器负责对这些绘制请求进行解释,然后把这些处理过的请求发送给图形显示硬件,这样就实现了绘图的目的。另外由于它这种特有的运行机制也实现了网络的透明性,即当应用程序与核心图形库不在同一台机器上时,其程序的代码完全跟它们在同一台机器上的一样,节约了通讯开销。
那么在Windows操作平台下,如果使用OpenGL图形库函数来开发应用程序呢?我们知道,使用GDI(图形设备接口)开发应用程序时,首先需要获得一个DeviceContext(设备描述表,简称DC),然后才能在这个DC下完成绘图工作,这一过程就类似于现实生活中纸和笔的关系,DC就是纸,而象刷子、画笔这样的GDI对象就是笔。从Windows内部运行机制来分析,DC应该理解为状态保持器,就是它可以而且必须保存当前系统的状态,这些状态包括:当前的画笔、刷子等GDI的具体类型(颜色、粗细等),当前的调色板类型以及系统的其他信息。当用户开始在DC上进行绘制工作时,系统就会先查看DC中相应的当前状态值,然后利用这些状态值进行图形绘制,如果用户希望改变当前状态值,那么可以通过SelectObject这样的Win32函数来将指定的状态或者对象选入DC即可。
实际上基于OpenGL的应用程序也是这样的,只是这里不是直接在DC上进行绘制工作,而是通过RenderContext(渲染描述表或者绘制描述表,简称为RC)这样一个桥梁在DC上进行绘制工作,对于程序来说实际上可以理解为就是在RC上绘制图形。另外只要RC不被释放(有效),那么就可以进行绘制工作;相比之下,DC却需要不断的创建和释放。
所以要使用OpenGL图形库进行图形应用开发,首先要获得RC,然后要将其设置为"当前RC",最后后面所有的绘制工作都是在"当前RC"下面进行的,直到"当前RC"无效为止。
1、核心库,包含的函数有115个,它们是最基本的函数,其前缀是gl;这部分函数用于常规的、核心的图形处理,由gl.dll来负责解释执行。核心库中的函数可以进一步分为以下几类函数。
(1)绘制基本几何图元的函数。
glBegain()、glEnd()、glNormal*()、glVertex*()。
(2)矩阵操作、几何变换和投影变换的函数。
矩阵入栈函数glPushMatrix(),矩阵出栈函数glPopMatrix(),装载矩阵函数glLoadMatrix(),矩阵相乘函数glMultMatrix(),当前矩阵函数 glMatrixMode()和矩阵标准化函数glLoadIdentity(),几何变换函数glTranslate*()、glRotate*()和glScale*(),投影变换函数glOrtho()、glFrustum()和视口变换函数glViewport()等等。
(3)颜色、光照和材质的函数。
如设置颜色模式函数glColor*()、glIndex*(),设置光照效果的函数glLight*()、glLightModel*()和设置材质效果函数glMaterial()等等。
(4)显示列表函数。
主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glCallList()和glDeleteLists()等。
(5)纹理映射函数。
主要有一维纹理函数glTexImage1D()、二维纹理函数glTexImage2D()、设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()等。
(6)特殊效果函数。
融合函数glBlendFunc()、反走样函数glHint()和雾化效果glFog*()。
(7)光栅化、象素操作函数。
像素位置glRasterPos*()、线型宽度glLineWidth()、多边形绘制模式glPolygonMode(),读取象素glReadPixel()、复制象素glCopyPixel()等。
(8)选择与反馈函数。
主要有渲染模式glRenderMode()、选择缓冲区glSelectBuffer()和反馈缓冲区glFeedbackBuffer()等。
(9)曲线与曲面的绘制函数。
生成曲线或曲面的函数glMap*()、glMapGrid*(),求值器的函数glEvalCoord*()glEvalMesh*()。
(10)状态设置与查询函数。主要有glGet*()、glEnable()、glGetError()等。
2、实用库(OpenGLutilitylibrary,GLU),包含的函数功能更高一些,如绘制复杂的曲线曲面、高级坐标变换、多边形分割等,共有43个,前缀为glu。Glu函数通过调用核心库的函数,为开发者提供相对简单的用法,实现一些较为复杂的操作。此类函数由glu.dll来负责解释执行。主要包括了以下几种:
(1)辅助纹理贴图函数。
有gluScaleImage()、gluBuild1Dmipmaps()、gluBuild2Dmipmaps()等。
(2)坐标转换和投影变换函数。
定义投影方式函数gluPerspective()、gluOrtho2D()、gluLookAt(),拾取投影视景体函数gluPickMatrix(),投影矩阵计算gluProject()和gluUnProject()等。
(3)多边形镶嵌工具。
有gluNewTess()、gluDeleteTess()、gluTessCallback()、gluBeginPolygon()gluTessVertex()、gluNextContour()、gluEndPolygon()等。
(4)二次曲面绘制工具。
主要有绘制球面、锥面、柱面、圆环面gluNewQuadric()、gluSphere()、gluCylinder()、gluDisk()、gluPartialDisk()、gluDeleteQuadric()等等。
(5)非均匀有理B样条绘制工具。
主要用来定义和绘制Nurbs曲线和曲面,包括gluNewNurbsRenderer()、gluNurbsCurve()、gluBeginSurface()、gluEndSurface()、gluBeginCurve()、gluNurbsProperty()等函数。
(6)错误反馈工具。
获取出错信息的字符串gluErrorString()等。
3、OpenGL辅助库(OpenGLauxiliarylibrary,GLAUX),包括简单的窗口管理、输入事件处理、某些复杂三维物体绘制等函数,共有31个,前缀为aux。此类函数由glaux.dll来负责解释执行。辅助库函数主要包括以下几类。
(1)窗口初始化和退出函数。
auxInitDisplayMode()和auxInitPosition()。
(2)窗口处理和时间输入函数。
auxReshapeFunc()、auxKeyFunc()和auxMouseFunc()。
(3)颜色索引装入函数。
auxSetOneColor()。
(4)三维物体绘制函数。
包括了两种形式网状体和实心体,如绘制立方体auxWireCube()和auxSolidCube()。这里以网状体为例,长方体auxWireBox()、环形圆纹面auxWireTorus()、圆柱auxWireCylinder()、二十面体auxWireIcosahedron()、八面体auxWireOctahedron()、四面体auxWireTetrahedron()、十二面体auxWireDodecahedron()、圆锥体auxWireCone()和茶壶auxWireTeapot()。绘制实心体只要将上述函数中的确"Wire"更换成"Solid"就可以了。
(5)其他。
背景过程管理函数auxIdleFunc();程序运行函数auxMainLoop()。
4、OpenGL工具库(OpenGLUtility Toolkit)
包含大约30多个函数,函数名前缀为glut,此函数由glut.dll来负责解释执行。这部分函数主要包括:
(1)窗口操作函数
窗口初始化、窗口大小、窗口位置等函数glutInit()glutInitDisplayMode()、glutInitWindowSize()glutInitWindowPosition()等。
(2)回调函数。
响应刷新消息、键盘消息、鼠标消息、定时器函数等,glutDisplayFunc()、glutPostRedisplay()、glutReshapeFunc()、glutTimerFunc()、glutKeyboardFunc()、glutMouseFunc()。
(3)创建复杂的三维物体。这些和aux库的函数功能相同。创建网状体和实心体。如glutSolidSphere()、glutWireSphere()等。
(4)菜单函数
创建添加菜单的函数glutCreateMenu()、glutSetMenu()、glutAddMenuEntry()、glutAddSubMenu()和glutAttachMenu()。
(5)程序运行函数。
glutMainLoop()。
5、16个WGL函数,专门用于OpenGL和Windows窗口系统的联接,其前缀为wgl,主要用于创建和选择图形操作描述表(renderingcontexts)以及在窗口内任一位置显示字符位图。这类函数主要包括以下几类
(1)绘图上下文相关函数。
wglCreateContext()、wglDeleteContext()、wglGetCurrentContent()、wglGetCurrentDC()wglDeleteContent()等。
(2)文字和文本处理函数。
wglUseFontBitmaps()、wglUseFontOutlines()。
(3)覆盖层、地层和主平面层处理函数。
wglCopyContext()、wglCreateLayerPlane()、wglDescribeLayerPlane()、wglReakizeLayerPlatte()等。
(4)其他函数。
wglShareLists()、wglGetProcAddress()等。
6、另外,还有五个Win32函数用来处理像素格式(pixelformats)和双缓存。由于它们是对Win32系统的扩展,因此不能应用在其它OpenGL平台上。
(二)OpenGL数据类型
与C语言相对应,OpenGL中也有整数、字节、浮点数等数据类型,为了说明两者的对应关系,下表将OpenGL的数据类型与相应的C类型进行了对比:
前缀 数据类型 相应C语言类型OpenGL类型
b8-bit integer signed char GLbyte
s 16-bit integer short GLshort
i 32-bit integer long GLint,GLsizei
f 32-bit floating-pointfloat GLfloat,GLclampf
d 64-bit floating-point doubleGLdouble,GLclampd
ub 8-bit unsigned integer unsigned charGLubyte,GLboolean
us 16-bit unsigned integer unsigned shortGLushort
ui 32-bit unsigned integer unsigned longGLuint,GLenum,GLbitfield
表一、OpenGL数据类型表
此外,OpenGL也定义GLvoid类型,如果用C语言编写,可以用它替代void类型。
(三)OpenGL库函数的命名规律
了解了OpenGL的数据类型,让我们再回过头来看看OpenGL库函数的命名规律。所有OpenGL函数采用了以下格式:
<库前缀><根命令><可选的参数个数><可选的参数类型>
库前缀有gl、glu、aux、glut、wgl、glx等等,分别表示该函数属于OpenGL某开发库等,从函数名后面中还可以看出需要多少个参数以及参数的类型。I代表int型,f代表float型,d代表double型,u代表无符号整型。注意,有的函数参数类型后缀前带有数字2、3、4。2代表二维,3代表三维,4代表alpha值(以后介绍)。有些OpenGL函数最后带一个字母v,表示函数参数可用一个指针指向一个向量(或数组)来替代一系列单个参数值。下面两种格式都表示设置当前颜色为红色,二者等价。
glColor3f(1.0,0.0,0.0);等价于:
floatcolor_array[]={1.0,0.0,0.0};
glColor3fv(color_array);
除了以上基本命名方式外,还有一种带"*"星号的表示方法,例如glColor*(),它表示可以用函数的各种方式来设置当前颜色。同理,glVertex*v()表示用一个指针指向所有类型的向量来定义一系列顶点坐标值。
核心函数说明
glAccum操作累加缓冲区
glAddSwapHintRectWIN定义一组被SwapBuffers拷贝的三角形
glAlphaFunc允许设置alpha检测功能
glAreTexturesResident决定特定的纹理对象是否常驻在纹理内存中
glArrayElement定义一个被用于顶点渲染的数组成分
glBegin,glEnd定义一个或一组原始的顶点
glBindTexture允许建立一个绑定到目标纹理的有名称的纹理
glBitmap绘制一个位图
glBlendFunc特殊的像素算法
glCallList执行一个显示列表
glCallLists执行一列显示列表
glClear用当前值清除缓冲区
glClearAccum为累加缓冲区指定用于清除的值
glClearColor为色彩缓冲区指定用于清除的值
glClearDepth为深度缓冲区指定用于清除的值
glClearStencil为模板缓冲区指定用于清除的值
glClipPlane定义被裁剪的一个平面几何体
glColor设置当前色彩
glColorMask允许或不允许写色彩组件帧缓冲区
glColorMaterial使一个材质色彩指向当前的色彩
glColorPointer定义一列色彩
glColorTableEXT定义目的一个调色板纹理的调色板的格式和尺寸
glColorSubTableEXT定义目的纹理的调色板的一部分被替换
glCopyPixels拷贝帧缓冲区里的像素
glCopyTexImage1D将像素从帧缓冲区拷贝到一个单空间纹理图象中
glCopyTexImage2D将像素从帧缓冲区拷贝到一个双空间纹理图象中
glCopyTexSubImage1D从帧缓冲区拷贝一个单空间纹理的子图象
glCopyTexSubImage2D从帧缓冲区拷贝一个双空间纹理的子图象
glCullFace定义前面或后面是否能被精选
glDeleteLists删除相邻一组显示列表
glDeleteTextures删除命名的纹理
glDepthFunc定义用于深度缓冲区对照的数据
glDepthMask允许或不允许写入深度缓冲区
glDepthRange定义z值从标准的设备坐标映射到窗口坐标
glDrawArrays定义渲染多个图元
glDrawBuffer定义选择哪个色彩缓冲区被绘制
glDrawElements渲染数组数据中的图元
glDrawPixels将一组像素写入帧缓冲区
glEdgeFlag定义一个边缘标志数组
glEdgeFlagPointer定义一个边缘标志数组
glEnable,glDisable 打开或关闭OpenGL的特殊功能
glEnableClientState,glDisableClientState分别打开或关闭数组
glEvalCoord求解一维和二维贴图
glEvalMesh1,glEvalMesh2求解一维和二维点或线的网格
glEvalPoint1,glEvalPoint2生成及求解一个网格中的单点
glFeedbackBuffer控制反馈模式
glFinish等待直到OpenGL执行结束
glFlush在有限的时间里强制OpenGL的执行
glFogf,glFogi,glFogfv,glFogiv定义雾参数
glFrontFace定义多边形的前面和背面
glFrustum当前矩阵乘上透视矩阵
glGenLists生成一组空的连续的显示列表
glGenTextures生成纹理名称
glGetBooleanv,glGetDoublev,glGetFloatv,glGetIntegerv返回值或所选参数值
glGetClipPlane返回特定裁减面的系数
glGetColorTableEXT从当前目标纹理调色板得到颜色表数据
glGetColorTableParameterfvEXT,glGetColorTableParameterivEXT从颜色表中得到调色板参数
glGetError返回错误消息
glGetLightfv,glGetLightiv返回光源参数值
glGetMapdv,glGetMapfv,glGetMapiv返回求值程序参数
glGetMaterialfv,glGetMaterialiv返回材质参数
glGetPixelMapfv,glGetpixelMapuiv,glGetpixelMapusv返回特定的像素图
glGetPointerv返回顶点数据数组的地址
glGetPolygonStipple返回多边形的点图案
glGetString返回描述当前OpenGl连接的字符串
glGetTexEnvfv返回纹理环境参数
glGetTexGendv,glGetTexGenfv,glGetTexGeniv返回纹理坐标生成参数
glGetTexImage返回一个纹理图象
glGetTexLevelParameterfv,glGetTexLevelParameteriv返回特定的纹理参数的细节级别
glGetTexParameterfv,glGetTexParameteriv返回纹理参数值
glHint定义实现特殊的线索
glIndex建立当前的色彩索引
glIndexMask控制写色彩索引缓冲区里的单独位
GlIndexPointer定义一个颜色索引数组
glInitName初始化名字堆栈
glInterleavedArrays同时定义和允许几个在一个大的数组集合里的交替数组
glIsEnabled定义性能是否被允许
glIsList检测显示列表的存在
glIsTexture确定一个名字对应一个纹理
glLightf,glLighti,glLightfv,glLightiv设置光源参数
glLightModelf,glLightModeli,glLightModelfv,glLightModeliv设置光线模型参数
glLineStipple设定线点绘图案
glLineWidth设定光栅线段的宽
glListBase为glcallList设定显示列表的基础
glLoadIdentity用恒等矩阵替换当前矩阵
glLoadMatrixd,glLoadMatrif用一个任意矩阵替换当前矩阵
glLoadName将一个名字调入名字堆栈
glLogicOp为色彩索引渲染定义一个逻辑像素操作
glMap1d,glMap1f定义一个一维求值程序
glMap2d,glMap2f定义一个二维求值程序
glMapGrid1d,glMapGrid1f,glMapgrid2d,glMapGrid2f定义一个一维或二维网格
glMaterialf,glMateriali,glMateriafv,glMaterialiv为光照模型定义材质参数
glMatrixMode定义哪一个矩阵是当前矩阵
glMultMatrixd,glMultMatrixf用当前矩阵与任意矩阵相乘
glNewList,glEndList创建或替换一个显示列表
glNormal设定当前顶点法向
glNormalPointer设定一个法向数组
glOrtho用垂直矩阵与当前矩阵相乘
glPassThrough在反馈缓冲区做记号
glPixelMapfv,glPixelMapuiv,glPixelMapusv设定像素交换图
glPixelStoref,glpixelStorei设定像素存储模式
glPixelTransferf,glPixelTransferi设定像素存储模式
glPixelZoom设定像素缩放因数
glPointSize设定光栅点的直径
glPolygonMode选择一个多边形的光栅模式
glPolygonOffset设定OpenGL用于计算深度值的比例和单元
glPolygonStipple设定多边形填充图案
glPrioritizeTextures设定纹理固定的优先级
glPushAttrib,glPopAttrib属性堆栈的压入和弹出操作
glPushClientAttrib,glPopClientAttrib在客户属性堆栈存储和恢复客户状态值
glPushmatrix,glPopMatrix矩阵堆栈的压入和弹出操作
glPushName,glPopName名字堆栈的压入和弹出操作
glRasterPos定义像素操作的光栅位置
glreadBuffer为像素选择一个源色彩缓冲区
glReadPixels从帧缓冲区读取一组数据
glRectd,glRectf,glRecti,glRects,glRectdv,glRectfv,glRectiv,glRectsv绘制一个三角形
glRenderMode定义光栅模式
glRotated,glRotatef将旋转矩阵与当前矩阵相乘
glScaled,glScalef将一般的比例矩阵与当前矩阵相乘
glScissor定义裁减框
glSelectBuffer为选择模式值建立一个缓冲区
glShadeModel选择平直或平滑着色
glStencilFunc为模板测试设置功能和参照值
glStencilMask控制在模板面写单独的位
glStencilOp设置激活模式测试
glTexCoord设置当前纹理坐标
glTexCoordPointer定义一个纹理坐标数组
glTexEnvf,glTexEnvi,glTexEnvfv,glTexEnviv设定纹理坐标环境参数
glTexGend,glTexgenf,glTexGendv,glTexGenfv,glTexGeniv控制纹理坐标的生成
glTexImage1D定义一个一维的纹理图象
glTexImage2D定义一个二维的纹理图
glTexParameterf,glTexParameteri,glTexParameterfv,glTexParameteriv设置纹理参数
glTexSubImage1D定义一个存在的一维纹理图像的一部分,但不能定义新的纹理
glTexSubImage2D定义一个存在的二维纹理图像的一部分,但不能定义新的纹理
glTranslated,glTranslatef将变换矩阵与当前矩阵相乘
glVertex定义一个顶点
glVertexPointer设定一个顶点数据数组
glViewport设置视窗[OpenGL应用函数库]
gluBeginCurve,gluEndCurve定义一条不一至的有理的NURBS曲线
gluBeginPolygon,gluEndPolygon定义一个非凸多边形
gluBeginSurface,gluEndSurface定义一个NURBS曲线
gluBeginTrim,gluEndTrim定义一个NURBS整理循环
gluBuild1Dmipmaps建立一维多重映射
gluBuild2Dmipmaps建立二维多重映射
gluCylinder绘制一个圆柱
gluDeleteNurbsRenderer删除一个NURBS对象
gluDeleQuadric删除一个二次曲面对象
gluDeleteTess删除一个镶嵌对象
gluDisk绘制一个盘子
gluErrorString根据OpenGL或GLU错误代码产生错误字符串
gluGetNutbsProperty得到一个NURBS属性
gluGetString得到一个描述GLU版本号或支持GLU扩展调用的字符串
gluGetTessProperty得到一个镶嵌对象
gluLoadSamplingMatrices加载NUMRBS例子和精选矩阵
gluLookAt设定一个变换视点
gluNewNurbsRenderer创建一个NURBS对象
gluNewQuadric建立一个二次曲面对象
gluNewTess建立一个镶嵌对象
gluNextContour为其他轮廓的开始做标记
gluNurbsCallback为NURBS对象设定一个回调
gluNnrbsCurve设定一个NuRBS曲线的形状
gluNurbsProperty设定一个NURBS属性
gluNurbsSurface定义一个NURBS表面的形状
gluOrtho2D定义一个二位正交投影矩阵
gluPartialDisk绘制一个盘子的弧
gluPerspective设置一个透视投影矩阵
gluPickMatrix定义一个拾取区间
gluProject将对象坐标映射为窗口坐标
gluPwlCurve描述一个分段线性NURBS修剪曲线
gluQuadricCallback为二次曲面对象定义一个回调
gluQuadricDrawStyle.为二次曲面设定合适的绘制风格
gluQuadricNormals定义二次曲面所用的法向的种类
gluQuadricOrientation定义二次曲面内部或外部方向
gluQuadricTexture定义是否带二次其面做纹理帖图
gluScaleImage将图象变换为任意尺寸
gluSphere绘制一个球体
gluTessBeginContour,gluTessEndContour划定一个边界描述
gluTessBeginPolygon,gluTessEndPolygon划定一个多边形描述
gluTessCallback为镶嵌对象定义一个回调
gluTessNormal为一个多边行形定义法向
gluTessProperty设置镶嵌对象的属性
gluTessVertex定义在一个多边形上的顶点
gluUnProject将窗口坐标映射为对象坐标