《OpenGL编程基础.ppt》由会员分享,可在线阅读,更多相关《OpenGL编程基础.ppt(63页珍藏版)》请在三一办公上搜索。
1、2023/7/7,华中科技大学计算机学院 李国宽,1,1、OpenGL简介 OpenGL(Open Graphics Library,开放图形库),是一个二维/三维的计算机图形和模型库,它源于SGI(Silicon Graphics inc.)公司为其图形工作站开发的IRIS GL,在跨平台移植过程中发展成为OpenGL。目前,OpenGL已成为开放的国际图形标准。,一、OpenGL框架,2023/7/7,2,OpenGL的功能:模型绘制 绘制点、线和多边形,构造三维模型。模型观察 建立变换(坐标变换,投影变换,视窗变换)。颜色模式的指定:RGBA模式和颜色索引模式 光照应用 图象效果增强:反
2、走样、混合和雾化 位图和图象处理 纹理映射 实时动画:双缓存技术(double buffer)交互技术 提供人机交互的接口。,OpenGL的特点从程序开发人员的角度来看,OpenGL是一组绘图命令的API集合。利用这些API能够方便地描述二维和三维几何物体,并控制这些物体按某种方式绘制到显示缓冲区中。OpenGL的API集提供了物体描述、平移、旋转、缩放、光照、纹理、材质、像素、位图、文字、交互以及提高显示性能等方面的功能,基本涵盖了开发二、三维图形程序所需的各个方面。与一般的图形开发工具相比,OpenGL具有以下几个突出特点:,(1)跨平台特性 OpenGL与硬件、窗口和操作系统是相互独立的
3、。为了构成一个完整功能的图形处理系统,其设计实现共分 5 层:图形硬件、操作系统、窗口系统、OpenGL和应用软件。因而,OpenGL可以集成到各种标准窗口和操作系统中。例如,操作系统包括UNIX,Windows NT,Windows 95/98,DOS等;窗口系统包括X Windows,Microsoft Windows等。OpenGL图形函数定义独立于任何程序设计语言,在各种编程语言中,如C,C+,FORTRAIN,Ada和Java等,都可以调用OpenGL的库函数。,(2)应用的广泛性OpenGL是目前最主要的二、三维交互式图形应用程序开发环境,已成为业界最受推荐的图形应用编程接口。自从
4、1992年发表以来,OpenGL已被广泛地应用于CAD/CAM、三维动画、数字图像处理以及虚拟现实等领域,Kinetix公司的3D Studio Max就是突出的代表。无论是在PC机上,还是在工作站甚至是大型机和超级计算机上,OpenGL都能表现出它的高性能和强大威力。,(3)网络透明性 建立在客户/服务器模型上的网络透明性是OpenGL的固有特性,它允许一个运行在工作站上的进程在本机或通过网络在远程工作站上显示图形。利用这种性质能够均衡各工作站的工作负荷,共同承担图形应用任务。(4)高质量和高性能 无论是在CAD/CAM、三维动画还是可视化仿真等领域,OpenGL高质量和高效率的图形生成能力
5、都能得到充分的体现。在这些领域中,开发人员可以利用OpenGL制作出效果逼真的二、三维图像来。,(5)出色的编程特性 OpenGL在各种平台上已有多年的应用实践,加上严格的规范控制,因此OpenGL具有良好的稳定性。OpenGL具有充分的独立性与易使用性等。,2023/7/7,8,2、OpenGL的工作方式(1)体系结构 一个完整的窗口系统的OpenGL图形处理系统的结构如右图所示:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenGL,最上面的层为应用软件。,2023/7/7,9,(2)OpenGL的流水线 当应用程序进行OpenGL API函数调用时,OpenGL命令将
6、被放在一个命令缓冲区中,这样,命令缓冲区中包含了大量的命令、顶点数据和纹理数据。当这个缓冲区被清空时,缓冲区中的命令和数据都将传递给流水线的下一个阶段。,2023/7/7,10,(3)OpenGL状态机制 OpenGL的工作方式是一种状态机制,它可以进行各种状态或模式设置,这些状态或模式在重新改变它们之前一直有效。状态变量可以通过glEnable()、glDisable()这两个函数来设置成有效或无效状态。另外可以用下列四个函数来获取某个状态变量的值:glGetBooleanv()、glGetDoublev()、glGetFloatv()和glGetIntegerv()。,2023/7/7,1
7、1,3、OpenGL的组成 OpenGL是一种API,包括了多个图形函数,主要由以下函数库组成。(1)OpenGL核心库:gl(2)OpenGL实用程序库:glu(3)OpenGL编程辅助库:aux(4)OpenGL实用程序工具包(OpenGL utility toolkit,GLUT):glut(5)Windows专用库:wgl(6)Win32 API函数库,2023/7/7,12,4、OpenGL中的数据类型,2023/7/7,13,5、函数命名约定OpenGL函数都遵循一个命名约定,即采用以下格式:例如函数glColor3f(),gl表示这个函数来自库gl.h,color表示该函数用于颜
8、色设定,3f表示这个函数采用了三个浮点数参数。,2023/7/7,14,6、OpenGL中的颜色在OpenGL中,一种颜色用红、绿、蓝成分的混合来表示,每种成分的值范围是0.0到1.0。,OpenGL初步编程,在Windows下开发和创建一个OpenGL程序的基本步骤:第一步,选择一个编译环境,如VC+第二步,安装GLUT工具包 第三步,建立一个OpenGL工程 第四步,编译连接 第五步,执行程序,OpenGL初步编程,OpenGL库和头文件:动态库:opengl32.dll glu32.dll glut32.dll 放入windowssystem32目录下静态库:opengl32.lib g
9、lu32.lib glut32.lib放入VC安装目录的LIB目录下头文件:gl.h glu.h glut.h放入VC安装目录的IncludeGL文件夹下,程序清单1.1:在窗口内绘制一个矩形/GLRect.c#include#include#include#include/函数RenderScene用于在窗口中绘制需要的图形void RenderScene(void)/用当前清除色清除颜色缓冲区,即设定窗口的背景色glClear(GL_COLOR_BUFFER_BIT);/设置当前绘图使用的RGB颜色 glColor3f(1.0f,0.0f,0.0f);/使用当前颜色绘制一个填充的矩形glR
10、ectf(100.0f,150.0f,150.0f,100.0f);/刷新OpenGL命令队列glFlush();,/函数ChangeSize是窗口大小改变时调用的登记函数void ChangeSize(GLsizei w,GLsizei h)if(h=0)h=1;/设置视区尺寸glViewport(0,0,w,h);/重置坐标系统,使投影变换复位glMatrixMode(GL_PROJECTION);glLoadIdentity();/建立修剪空间的范围 if(w=h)glOrtho(0.0f,250.0f,0.0f,250.0f*h/w,1.0f,-1.0f);else glOrtho(0
11、.0f,250.0f*w/h,0.0f,250.0f,1.0f,-1.0f);glMatrixMode(GL_MODELVIEW);glLoadIdentity();/函数SetupRC用于初始化,常用来设置场景渲染状态void SetupRC(void)/设置窗口的清除色为白色 glClearColor(1.0f,1.0f,1.0f,1.0f);,void main(void)/初始化GLUT库OpenGL窗口的显示模式glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);/创建一个名为GLRect的窗口glutCreateWindow(GLRect);/设置当
12、前窗口的显示回调函数和窗口再整形回调函数glutDisplayFunc(RenderScene);glutReshapeFunc(ChangeSize);SetupRC();/启动主GLUT事件处理循环glutMainLoop();,GLRect程序运行结果,2023/7/7,21,1、画点、线和面glBegin(GL_POINTS);glVertex3f(0.0f,0.0f,0.0f);glVertex3f(10.0f,10.0f,10.0f);glEnd();计算机中的图元只是把一组顶点或顶点列表解释为屏幕上绘制的某些形状,而顶点是用函数glVertex3f来定义,该函数中的参数指明定义点
13、的x、y和z坐标。,二、用OpenGL绘图,2023/7/7,22,2023/7/7,23,(1)点的大小void glPointSize(GLfloat size);GLfloat sizes2;/保存绘制点的尺寸范围GLfloat step;/保存绘制点尺寸的步长glGetFloarv(GL_POINT_SIZE_RANGE,sizes);glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);(2)线宽void glLineWidth(GLfloat width)GLfloat sizes2;/保存线宽的尺寸范围GLfloat step;/保存线宽尺寸的
14、最小间隔glGetFloarv(GL_LINE_WIDTH_RANGE,sizes);glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&step);,2023/7/7,24,(3)线型glEnable(GL_LINE_STIPPLE);glLineStipple(GLint factor,GLushort pattern);pattern是一个16位值,他指定了画线时所用的模式。每一位代表线段的一部分是开还是关。默认情况下,每一位对应一个象素,但factor参数充当倍数可以增加模式的宽度。在应用模式时,pattern是逆向使用的,即模式的最低有效位最先作用于指点线段
15、。,2023/7/7,25,2、绕法与多边形模式 在绘制三角形的过程中,三个顶点将三角形封闭的过程是有序的,即三角形的构成路径具有方向性,我们把指定顶点时顺序和方向的组合称为“绕法”。绕法是任何多边形图元的一个重要特性。一般默认情况下,OpenGL认为逆时针绕法的多边形是正对着的。glFrontFace(GL_CW);glFrontFace(GL_CCW);,2023/7/7,26,函数glPolygonMode用于设定多边形模式:glPolygonMode(GLenum face,GLenum mode);其中,参数face用于指定多边形的哪一个面受到模式改变的影响(GL_FRONT,GL_
16、BACK或GL_FRONT_AND_BACK)。参数mode用于指定新的绘图模式。GL_FILL是默认值,生成填充的多边形;GL_LINE生成多边形的轮廓;而GL_POINT只画出顶点。,2023/7/7,27,3、多边形颜色的设置 在OpenGL中,颜色实际上是对各个顶点而不是对各个多边形指定的。(1)glShadeModel(GL_FLAT)告诉OpenGL用指定多边形最后一个顶点时的当前颜色作为填充多边形的纯色,唯一例外是GL_POLYGON图元,它采用的是第一个顶点的颜色。(2)glShadeModel(GL_SMOOTH)告诉OpenGL从各个顶点给三角形投上光滑的阴影,试图在为各个
17、顶点指定的颜色之间进行插值。,Gouraud明暗处理通常算法为:先用多边形顶点的光强线性插值出当前扫描线与多边形边交点处的光强,然后再用交点的光强线插值处扫描线位于多边形内区段上每一象素处的光强值。采用Gouraud明暗处理不但可以使用多边形表示的曲面光强连续,而且计算量很小。,2023/7/7,29,4、深度测试 深度测试是一种移除被挡住表面的有效技术。为了启用深度测试,只要调用:glEnable(GL_DEPTH_TEST);glDisable(GL_DEPTH_TEST);另外为了使深度缓冲区正常完成深度测试功能,在每次渲染场景时,必须先清除深度缓冲区:glClear(GL_DEPTH_
18、BUFFER_BIT);,2023/7/7,30,5、多边形构造规则(1)所有多边形都必须是平面的。(2)第二条规则是多边形的边缘决不能相交,而且多边形必须是凸的。解决:对于非凸多边形,可以把它分割成几个凸多边形(通常是三角形),再将它绘制出来。问题:轮廓图形状态会看到组成大表面的所有小三角形。处理OpenGL提供了一个特殊标记来处理这些边缘,称为边缘标记。glEdgeFlag(True)glEdgeFlag(False),1、OpenGL中的变换(1)视图变换:指定观察者或摄影机的位置;(2)模型变换:在场景中移动对象;(3)模型视图变换:描述视图变换与模型变换的对偶性;(4)投影变换:对视
19、见空间进行修剪和改变大小;(5)视见区变换:对窗口的最终输出进行缩放;,三、图形的变换,2、模型视图矩阵(1)平移 void glTranslated(f)(GLdouble x,GLdouble y,GLdouble z);(2)旋转void glRotated(f)(GLdouble angle,GLdouble x,GLdouble y,GLdouble z);(3)比例 void glScaled(f)(GLdouble x,GLdouble y,GLdouble z);,矩阵的操作glMatrixMode(GLenum mode);参数mode用于确定将哪个矩阵堆栈用于矩阵操作。GL
20、_MODELVIEW:模型视图矩阵堆栈GL_PROJECTION:投影矩阵堆栈GL_TEXTURE:纹理矩阵堆栈,3、单位矩阵 glTranslatef(10.0f,0.0f,0.0f);glutSolidSphere(1.0f,15,15);glTranslatef(0.0f,10.0f,0.0f);glutSolidSphere(1.0f,15,15);,glMatrixMode(GL_MODELVIEW);glLoadIdentity();,4、矩阵堆栈 OpenGL为模型视图矩阵和投影矩阵各维护着一个“矩阵堆栈”,可以把当前矩阵压到堆栈中保存它,然后对当前矩阵进行修改。把矩阵弹出堆栈即
21、可恢复。使用的函数如下:void glPushMatrix(void);void glPopMatrix(void);,5、投影变换 OpenGL中只提供了两种投影方式,一种是平行投影(正射投影),另一种是透视投影。在投影变换之前必须指定当前处理的是投影变换矩阵:glMAtrixMode(GL_PROJECTION);glLoadIdentity();,(1)平行投影 平行投影,它的视景体是一个矩形的平行管道,也就是一个长方体,其特点是无论物体距离相机多远,投影后的物体大小尺寸不变。void glOrtho(GLdouble left,GLdouble right,GLdouble botto
22、m,GLdouble top,GLdouble near,GLdouble far);这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。,void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top);它是一个特殊的正射投影函数,主要用于二维图像到二维屏幕上的投影。它的near和far缺省值分别为-1.0和1.0,所有二维物体的Z坐标都为0.0。因此它的裁剪面是一个左下角点为(left,bottom)、右上角点为(right,top)的矩形。,(2)透视投影 void glFrustum(GL
23、double left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);此函数创建一个透视投影矩阵,并且用这个矩阵乘以当前矩阵。它的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。,void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLd
24、ouble zFar);它也创建一个对称透视视景体,但它的参数定义于前面的不同,其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在X-Z平面(垂直方向上的可见区域)的角度,范围是0.0,180.0;参数aspect是投影平面的纵横比(宽度与高度的比值);参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离。,6、高级矩阵处理 glfloat m=1.0f,0.0f,3.0f,0.0f,0.0f,1.0f,0.0f,1.0f,0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,0.0f,1.0f,;glMatrixMode(GL_MODELVIE
25、W);glLoadMatrixf(m);,当光照射到一个物体表面上时,会出现三种情形。首先,光可以通过物体表面向空间反射,产生反射光。其次,对于透明体,光可以穿透该物体并从另一端射出,产生透射光。最后,部分光将被物体表面吸收而转换成热。在上述三部分光中,仅仅是透射光和反射光能够进入人眼产生视觉效果。,四、光照处理,(1)环境光(Ambient Light)环境光不来自于任何特殊的方向,他有光源,但是被周围的房间或场景多次反射,以致于变得没有方向。被环境光照射的物体表面的各个方向都均等受光。(2)散射光(Diffuse Light)光来自某个方向,被物体表面均匀地反射。光是被均匀反射回去的,它直
26、射的物体表面比从某个角度照射过来时要亮。,(3)镜面光(Specular Light)镜面光也有方向性,但被强烈地反射到另一特定的方向。高亮度的镜面光能够在被照射的物体表面上产生称之为亮斑的亮点。任何一个光源都是由环境光、散射光和镜面光三种光照成分组成,各成分的定义是由RGBA值定义的。,5.材质 OpenGL用材料对光的红、绿、蓝三原色的反射率来近似定义材料的颜色。象光源一样,材料颜色也分成环境、漫反射和镜面反射成分,它们决定了材料对环境光、漫反射光和镜面反射光的反射程度。在进行光照计算时,材料对环境光的反射率与每个进入光源的环境光结合,对漫反射光的反射率与每个进入光源的漫反射光结合,对镜面
27、光的反射率与每个进入光源的镜面反射光结合。,材质的颜色实际决定了反射光与入射光的百分比率:若OpenGL的光源颜色为(LR、LG、LB),材质颜色属性为(MR、MG、MB)。那么,最终到达眼睛的光的颜色为(LR*MR、LG*MG、LB*MB)三种光照成分的RGBA值叠加就形成了物体最终的颜色。当任何一种颜色成分大于1.0,就用1.0计算。,6.加入光照(1)glEnable(GL_LIGHTING)指定OpenGL可以利用材质属性和光照参数决定场景中每个顶点的颜色。,(2)glLightModelfv(f,i,iv)(Glenum pname,const GLfloat*param)指定光照模
28、型GL_LIGHT_MODEL_AMBIENT:设置环境光GL_LIGHT_MODEL_LOCAL_VIEWER:定义视点,0表示镜面反射角度认为视线方向平行于z轴负向,否则镜面反射从视点坐标系的原点来计算。GL_LIGHT_MODEL_TWO_SIDE:启用双面关照,0.0时表示只有多边形表面的正面进行光照计算,否则正反两面都进行光照计算。,(3)glMaterialfv(GLenum face,GLenum pname,const GLfloat*params)Face参数:GL_FRONT;GL_BACK;GL_FRONT_AND_BACK。Pname参数:GL_AMBIENT:材质环境
29、反射RGBA值。GL_DIFFUSE:材质漫反射RGBA值。GL_SPECULAR:材质镜面反射RGBA值。GL_SHININESS:材质的RGBA镜面指数。,(4)glEnable(GL_COLOR_MATERIAL)启用颜色跟踪法,此时可以通过glColor设置材质属性。(5)glColorMaterial(Glenum face,Glenum mode)mode:指定哪个材质属性能够遵循当前的颜色。,GL_EMISSION;GL_AMBIENT;GL_DIFFUSE;GL_SPECULAR;GL_AMBIENT_AND_DIFFUSE。,7.使用点光源 OpenGL支持8种独立光源,它们
30、可以放置在场景中的任意位置,也可放在视见空间之外。当将光源放在无穷远处就可以得到平行的光线。光源发射光线射到多边形的表面,与平面成角度A,在以角度B反射进入观察者,通过这些角度可以计算光线照射的多边形表面的颜色。OpenGL有意让计算的位置就是多边形的顶点。通过计算各个顶点的颜色,再在各个顶点间进行光滑着色。,(1)法线矢量 从假想的平面(或者是多边形)上的一个顶点引出来的一条垂直向上的线称为法线矢量。glNormal3f(GLfloat x,GLfloat y,GLfloat z)指定法线矢量。OpenGL最后都将表面法线转化成单位法线,对于光照计算,所有的法线矢量都必须归一化。glEnab
31、le(GL_NORMALIZE)glEnable(GL_RESCALE_NORMALS)法线矢量的计算,(2)设置光源参数glLightf(GLenum light,GLenum pname,GLenum param)light:光源编号,pname:指定光源参数类型GL_AMBIENT:光照的环境RGBA浓度。GL_DIFFUSE:光照的漫射RGBA浓度。GL_SPECULAR:光照的镜面RGBA浓度。,(3)镜面光处理 使用glLightfv函数在光源中加入镜面光成分,为了出现镜面光效果,还要在材质属性中增加镜面成分。镜面指数:glMateriali(GL_FRONT,GL_SHININE
32、SS,128);GL_SHININESS属性设置材质的镜面指数,它说明如何确定镜面关亮斑的大小和聚焦程度。,(4)光的衰减 真实的光,离光源越远则光强越小。OpenGL的光衰减是通过光源的发光量乘以衰减因子计算出来的。缺省状态下,常数衰减因子是(1.0,0.0,0.0)。用户也可以自己定义这些值,如:glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,2.0);glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0);glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.5);注意:环境光
33、、漫反射光和镜面光的强度都衰减,只有辐射光和全局环境光的强度不衰减。,(5)聚光和多光源 定位光源可以定义成聚光灯形式,即将光的形状限制在一个圆锥内。OpenGL中聚光的定义有以下几步:a)定义聚光源位置。因为聚光源也是定向光源,所以他的位置同一般定向光一样。如:GLfloat light_pos=1.0,1.0,1.0,1.0;glLightfv(GL_LIGHT0,LIGHT_POSITION,light_pos);light_pos参数的最后一个分量为0,则光源为方向光源,分量为1,则光源为平行于负z轴的方向光源。,b)定义聚光截止角。参数GL_SPOT_CUTOFF给定光锥的轴与中心线
34、的夹角,也可说成是光锥顶角的一半。缺省时,这个参数为180.0,即顶角为360度,光向所有的方向发射,因此聚光关闭。一般在聚光启动情况下,聚光截止角限制在0.0,90.0 之间,如下面一行代码设置截止角为45度:glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0);,如果光照方向与光照到所照射的顶点方向之间的角度大于聚光截止角,那么光照完全被屏蔽。,c)定义聚光方向。聚光方向决定光锥的轴,其缺省值为(0.0,0.0,-1.0),即指向Z负轴。聚光方向也要进行几何变换,其结果保存在视点坐标系中。它的定义如下:GLfloat spot_dir=-1.0,-1.0,0.0;
35、glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spot_dir);,三个参数包含4个整数值或浮点数值,只有当聚光截止角不等于180.0时,此参数值才有效。,d)定义聚光指数。参数GL_SPOT_EXPONENT控制光的集中程度,光锥中心的光强最大,越靠边的光强越小,缺省时为0。glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,2.0);,此函数定义光照的浓度分布。有效的关照浓度是按照光照方向与光照到所照射的顶点方向之间的角度的余弦,并逐渐增加聚光源的指数进行衰减,这样较大的聚光指数会产生有更强聚焦效果的光源。,(6)光源的移动 OpenGL光
36、源的位置和方向与其它几何图元的位置和方向一样都必须经过变换矩阵的作用。当用glLight()说明光源的位置和方向时,位置和方向都要经过当前变换矩阵的作用并保存在视点坐标系中,注意投影矩阵变换对它们不起作用。OpenGL可通过调整光源函数和视点变换函数在程序中的相对位置来获得三种不同的效果:1)光源位置保持固定、2)光源绕静止物体移动、3)光源随视点移动,(7)辐射光通过给GL_EMISSION定义一个RGBA值,可以使物体看起来象发出这种颜色的光一样,以达到某种特殊效果。实际上,现实生活中的物体除光源外都不发光,但我们可以利用这一特性来模拟灯和其他光源。代码举例如下:GLfloat mat_emission=0.3,0.3,0.5,0.0;glMaterialfv(GL_FRONT,GL_EMISSION,mat_emission);这样,物体看起来稍微有点发光。,8.阴影 当物体阻止光源的光射到它后面的物体或表面时就会产生阴影。通常是通过把原物体压平、平放到平面表面的方法创建阴影。处理时需要压平模型视图投影矩阵,此外需要考虑光源的距离和方向,光源的方向决定阴影的形状、影响阴影的尺寸。,