• 1. Beyond TechnologyOpenGL基础知识 李斌0沈阳东软软件股份有限公司 AVNC 事业部
  • 2. 课程介绍培训内容 OpenGL基础知识。 面向对象 毕业设计人员&新员工。 培训目的 使参加培训人员,能够运用所讲OpenGL基础知识进行毕业设计及进行实际的项目开发。1沈阳东软软件股份有限公司 AVNC 事业部
  • 3. OpenGL(Open Graphics Library )简介OpenGL实际上是一种图形与硬件的接口。 OpenGL是个与硬件无关的软件接口,可以在不同的平台如Windows 、Unix、Linux、MacOS、OS/2之间进行移植。 OpenGL被设计为只有输出的,所以它只提供渲染功能。核心API没有窗口系统、音频、打印、键盘/鼠标或其它输入设备的概念。虽然这一开始看起来像是一种限制,但它允许进行渲染的代码完全独立于他运行的操作系统,允许跨平台开发。然而,有些整合于原生窗口系统的东西需要允许和宿主系统交互。这通过下列附加API实现:     * GLX - X11(包括透明的网络)     * WGL - Microsoft Windows 2沈阳东软软件股份有限公司 AVNC 事业部
  • 4. OpenGL 变换-相机模拟 3沈阳东软软件股份有限公司 AVNC 事业部
  • 5. OpenGL 变换-显示流程 4沈阳东软软件股份有限公司 AVNC 事业部
  • 6. OpenGL 变换-几何变换 void glTranslate{fd}(TYPE x,TYPE y,TYPE z) 三个函数参数就是目标分别沿三个轴向平移的偏移量。void glRotate{fd}(TYPE angle,TYPE x,TYPE y,TYPE z) 函数中第一个参数是表示目标沿从点(x,y,z)到原点的方向逆时针旋转的角度 ,后三个参数是旋转的方向点坐标。void glScale{fd}(TYPE x,TYPE y,TYPE z) 三个函数参数值就是目标分别沿三个轴向缩放的比例因子。5沈阳东软软件股份有限公司 AVNC 事业部
  • 7. OpenGL 变换-投影变换透视投影 void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far) 它创建一个透视视景体。其操作是创建一个透视投影矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值。6沈阳东软软件股份有限公司 AVNC 事业部
  • 8. OpenGL 变换-视口变换 glViewport(GLint x,GLint y,GLsizei width, GLsizei height); 这个函数定义一个视口。函数参数(x,y)是视口在屏幕窗口坐标系中的左下角点坐标,参数width和height分别是视口的宽度和高度。注意,在实际应用中,视口的长宽比率总是等于视景体裁剪面的长宽比率。如果两个比率不相等,那么投影后的图像显示于视口内时会发生变形。7沈阳东软软件股份有限公司 AVNC 事业部
  • 9. OpenGL 变换-裁减void glScissor( GLint x, GLint y, GLsizei width, GLsizei height ); 该函数用来设置剪裁区域。注意只有启用了GL_SCISSOR_TEST时, 绘制的内容才能被裁减。8沈阳东软软件股份有限公司 AVNC 事业部
  • 10. OpenGL 变换-矩阵操作void glLoadMatrix{fd}(const TYPE *m) 设置当前矩阵中的元素值。函数参数*m是一个指向16个元素(m0,m1,...,m15)的指针,这16个元素就是当前矩阵 M 中的元素,其排 列方式如下: * * * m0 m4 m8 m12 * M =* m1 m5 m9 m13 * * m2 m6 m10 m14 * * m3 m7 m11 M15 * * * void glMultMatrix{fd}(const TYPE *m) 用当前矩阵去乘*m所指定的矩阵,并将结果存放于*m中。当前矩阵可以是 void glPushMatrix(void); 将所有矩阵依次压入堆栈中 void glPopMatrix(void); 弹出堆栈顶部的矩阵 9沈阳东软软件股份有限公司 AVNC 事业部
  • 11. 颜色模式 OpenGL颜色模式一共有两个:RGB(RGBA)模式和颜色表模式。在RGB模式下,所有的颜色定义全用R、G、B三个值来表示,有时也加上Alpha值(与透明度有关),即RGBA模式。在颜色表模式下,每一个象素的颜色是用颜色表中的某个颜色索引值表示,而这个索引值指向了相应的R、G、B值。这样的一个表成为颜色映射(Color Map)。 10沈阳东软软件股份有限公司 AVNC 事业部
  • 12. RGBA模式 void glColor3{b s i f d ub us ui}(TYPE r,TYPE g,TYPE b); void glColor4{b s i f d ub us ui}(TYPE r,TYPE g,TYPE b,TYPE a); void glColor3{b s i f d ub us ui}v(TYPE *v); void glColor4{b s i f d ub us ui}v(TYPE *v); _____________________________________________________   后缀 数据类型 最小值 最小值映射 最大值 最大值映射 ______________________________________________________   b 1字节整型数 -128 -1.0 127 1.0 s 2字节整型数 -32,768 -1.0 32,767 1.0 i 4字节整型数 -2,147,483,648 -1.0 2,147,483,647 1.0 ub 1字节无符号整型数 0 0.0 255 1.0 us 2字节无符号整型数 0 0.0 65,535 1.0 ui 4字节无符号整型数 0 0.0 4,294,967,295 1.0 ______________________________________________________ 整型颜色值到浮点数的转换11沈阳东软软件股份有限公司 AVNC 事业部
  • 13. OpenGL纹理 纹理影射基本步骤 一、定义纹理; 二、控制滤波; 三、说明映射方式; 四、绘制场景,给出顶点的纹理坐标和几何坐标。12沈阳东软软件股份有限公司 AVNC 事业部
  • 14. OpenGL纹理-纹理定义 void glTexImage2D(GLenum target,GLint level,GLint components,GLsizei width,glsizei height,GLint border,GLenum format,GLenum type,const GLvoid *pixels); 参数target是常数GL_TEXTURE_2D。 参数level表示多级分辨率的纹理图像的级数,若只有一种分辨率,则level设为0。 参数components是一个从1到4的整数,指出选择了R、G、B、A中的哪些分量用于调整和混合,1表示选择了R分量,2表示选择了R和A两个分量,3表示选择了R、G、B三个分量,4表示选择了R、G、B、A四个分量。 参数width和height给出了纹理图像的长度和宽度,参数border为纹理边界宽度,它通常为0,width和height必须是2m+2b,这里m是整数,长和宽可以有不同的值,b是border的值。纹理映射的最大尺寸依赖于OpenGL,但它至少必须是使用64x64(若带边界为66x66), 若width和height设置为0,则纹理映射有效地关闭。 参数format和type描述了纹理映射的格式和数据类型,它们在这里的意义与在函数 glDrawPixels()中的意义相同,事实上,纹理数据与glDrawPixels()所用的数据有同样的格式。参数format可以是GL_COLOR_INDEX、GL_RGB、GL_RGBA、GL_RED、GL_GREEN、GL_BLUE、GL_ALPHA、GL_LUMINANCE或GL_LUMINANCE_ALPHA(注意,不能用GL_STENCIL_INDEX和GL_DEPTH_COMPONENT)。类似地,参数type是GL_BYPE、GL_UNSIGNED_BYTE、GL_SHORT、 GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_FLOAT或GL_BITMAP。 参数pixels包含了纹理图像数据,这个数据描述了纹理图像本身和它的边界。13沈阳东软软件股份有限公司 AVNC 事业部
  • 15. OpenGL纹理-纹理滤波 void glTexParameter{if}[v](GLenum target,GLenum pname,TYPE param); 控制纹素映射到片元(fragment)时怎样对待纹理。第一个参数target可以是GL_TEXTURE_1D或GL_TEXTURE_2D,它指出是为一维或二维纹理说明参数;后两个参数的可能值见下表所示。  ___________________________________________________________________  参 数 值____________________________________________________________________  GL_TEXTURE_WRAP_S GL_CLAMP GL_REPEAT   GL_TEXTURE_WRAP_T GL_CLAMP GL_REPEAT   GL_TEXTURE_MAG_FILTER GL_NEAREST GL_LINEAR   GL_TEXTURE_MIN_FILTER GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR __________________________________________________________________  放大和缩小滤波方式14沈阳东软软件股份有限公司 AVNC 事业部
  • 16. OpenGL纹理-映射方式 void glTexEnv{if}[v](GLenum target,GLenum pname,TYPE param); 设置纹理映射方式。参数target必须是GL_TEXTURE_ENV;若参数pname是GL_TEXTURE_ENV_MODE,则参数param可以是GL_DECAL、GL_MODULATE或GL_BLEND,以说明纹理值怎样与原来表面颜色的处理方式;若参数pname是GL_TEXTURE_ENV_COLOR,则参数param是包含四个浮点数(分别是R、G、B、a分量)的数组,这些值只在采用GL_BLEND纹理函数时才有用。  ___________________________________________________________________  pname参 数 param值____________________________________________________________________ GL_TEXTURE_ENV_MODE GL_DECAL(替换模式) GL_MODULATE(纹理颜色*几何图形颜色) GL_BLEND(混合模式,需要设置纹理环境颜色) GL_TEXTURE_ENV_COLOR RGBA分量数组 __________________________________________________________________  15沈阳东软软件股份有限公司 AVNC 事业部
  • 17. OpenGL纹理-纹理坐标 void gltexCoord{1234}{sifd}[v](TYPE coords); 设置当前纹理坐标,此后调用glVertex*()所产生的顶点都赋予当前的纹理坐标。对于 gltexCoord1*(),s坐标被设置成给定值,t和r设置为0,q设置为1;用gltexCoord2*() 可以设置s和t坐标值,r设置为0,q设置为1;对于gltexCoord3*(),q设置为1,其它坐 标按给定值设置;用gltexCoord4*()可以给定所有的坐标。使用适当的后缀(s,i,f或d)和 TYPE的相应值(GLshort、GLint、glfloat或GLdouble)来说明坐标的类型。注意,整型纹 理坐标可以直接应用,而不是象普通坐标那样被映射到[-1,1]之间。 str16沈阳东软软件股份有限公司 AVNC 事业部
  • 18. OpenGL基本图元-顶点OpenGL基本库提供了大量绘制各种类型图元的方法, 其中包括点、线、多边 形,有了这些图元,就可以建立比较复杂的模型了。 定义顶点 在OpenGL中,所有几何物体最终都由有一定顺序的顶点集来描述。函数 glVertex{234}{sifd}[v](TYPE coords)可以用二维、三维或齐次坐标定义顶点。举例如下:   glVertex2s(2,3); glVertex3d(0.0,1.0,3.1414926535); glVertex4f(2.4,1.0,-2.2,2.0);   GLfloat pp[3]={5.0,2.0,10.2}; glVertex3fv(pp);   第一例子表示一个空间顶点(2,3,0),第二个例子表示用双精度浮点数定义一个顶点,第 三个例子表示用齐次坐标定义一个顶点,其真实坐标为(1.2,0.5,-1.1),最后一个例子表示 用一个指针(或数组)定义顶点。 17沈阳东软软件股份有限公司 AVNC 事业部
  • 19. OpenGL基本图元-构造几何图元(1) 在实际应用中,通常用一组相关的顶点序列以一定的方式组织起来定义某个几何图元,而 不采用单独定义多个顶点来构造几何图元。在OpenGL中,所有被定义的顶点必须放在 glBegain()和glEnd()两个函数之间才能正确表达一个几何图元或物体,否则,glVertex*() 不完成任何操作。如:   glBegin(GL_POLYGON); glVertex2f(0.0,0.0); glVertex2f(0.0,3.0); glVertex2f(3.0,3.0); glVertex2f(4.0,1.5); glVertex2f(3.0,0.0); glEnd(); 以上这段程序定义了一个多边形,如果将glBegin()中的参数GL_POLYGON改为 GL_POINTS,则图形变为一组顶点(5个),见下图所示。 GL_POLYGON GL_POINTS 18沈阳东软软件股份有限公司 AVNC 事业部
  • 20. OpenGL基本图元-构造几何图元(2)函数glBegin(GLenum mode)标志描述一个几何图元的顶点列表的开始,其参数mode 表示几何图元的描述类型。所有类型及说明见下表所示。 函数glEnd()标志顶点列表的结束。 ____________________________________________________________________________ 类 型 说 明 ____________________________________________________________________________   GL_POINTS 单个顶点集 GL_LINES 多组双顶点线段 GL_POLYGON 单个简单填充凸多边形 GL_TRAINGLES 多组独立填充三角形 GL_QUADS 多组独立填充四边形 GL_LINE_STRIP 不闭合折线 GL_LINE_LOOP 闭合折线 GL_TRAINGLE_STRIP 线型连续填充三角形串 GL_TRAINGLE_FAN 扇形连续填充三角形串 GL_QUAD_STRIP 连续填充四边形串 ____________________________________________________________________________   几何图元类型和说明19沈阳东软软件股份有限公司 AVNC 事业部
  • 21. OpenGL基本图元-构造几何图元(3)几何图元类型 20沈阳东软软件股份有限公司 AVNC 事业部
  • 22. OpenGL基本图元-构造几何图元(4)图元扩展 点 void glPointSize(GLfloat size);   设置点的宽度(以象素为单位)。参数size必须大于0.0,缺省时为1.0。 线。 OpenGL能指定线的各种宽度和绘制不同的虚点线,如点线、虚线等。相应的函数形式如下:   void glLineWidth(GLfloat width); void glLineStipple(GLint factor,GLushort pattern); 设置线为当前的虚点模式。参数pattern是一系列的16位数(0或1),它重复地赋给所 指定的线。其中每一位代表一个象素,且从低位开始,1表示用当前颜色绘制一个象素(或 比例因子指定的个数),0表示当前不绘制,只移动一个象素位(或比例因子指定的个数)。 参数factor是个比例因子,它用来拉伸pattern中的元素,即重复绘制1或移动0,比如, factor为2,则碰到1时就连续绘制2次,碰到0时连续移动2个单元。factor的大小范围 限制在1到255之间。在绘制虚点线之前必须先启动一下,即调用函数glEnable(GL_LINE_STIPPLE); 若不用,则调用glDisable(GL_LINE_STIPPLE)关闭。21沈阳东软软件股份有限公司 AVNC 事业部
  • 23. OpenGL基本图元-构造几何图元(5)顶点数组 启用 glEnableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); 数据在哪里 void glVertexPointer( GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer ); size The number of coordinates per vertex. The value of size must be 2, 3, or 4. type The data type of each coordinate in the array using the following symbolic constants: GL_SHORT, GL_INT, GL_FLOAT, and GL_DOUBLE. stride The byte offset between consecutive vertices. When stride is zero, the vertices are tightly packed in the array. count The number of vertices, counting from the first, that are static. pointer A pointer to the first coordinate of the first vertex in the array. 22沈阳东软软件股份有限公司 AVNC 事业部
  • 24. OpenGL基本图元-构造几何图元(6)顶点数组 进行绘图 void glDrawArrays( GLenum mode, GLint first, GLsizei count ); mode The kind of primitives to render. The following constants specify acceptable types of primitives: GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON. first The starting index in the enabled arrays. count The number of indexes to render. 23沈阳东软软件股份有限公司 AVNC 事业部
  • 25. 绘制位图、图像(1) 位图和图像数据都是矩形像素阵列,他们之间的区别是,位图中每个像素只有一位信息,而图像中每个像素有多种信息(如R,G,B,A分量).24沈阳东软软件股份有限公司 AVNC 事业部
  • 26. 绘制位图、图像(2)位图 一个位图就是由0和1组成的矩形陈列,起到窗口中对应矩形位置的绘制掩模的作用。假定你正在绘制一幅位图,当前颜色为红色。在位图中为一个的每个地方,对应的象素将被红色象素取代。如果在位图中有个一0,那个象素的内容将不受影响。通常使用位图是为了在屏幕上绘制字符。 设置光栅位置 void glRasterPos{234}{sifd}{v}(TYPE x, TYPE y, TYPE z, TYPE w); 设定当前光栅位置。参数x,y,z和w说明了光栅位置的坐标。。如果glRasterPos2*()被使用,z被简单的设为0并且w总是被设为1;类似的,对glRasterPos3*(),w被设为1。 光栅位置的坐标变换为屏幕坐标的过程与glVertex*()命令所提供的坐标的变换过程完全一样(即,经模型视图和透视变换矩阵)。 25沈阳东软软件股份有限公司 AVNC 事业部
  • 27. 绘制位图、图像(3)绘制位图 void glBitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap ) Width和height参数说明位图的宽度和高度,以像素为单位。 用xorig和yorig定义位图的原点(正值将原点移向右上;负值将它移向左下) xmove和ymove说明在位图光栅化后加给光栅位置的增量。 bitmap是指向位图图象的指针。 注: 默认情况下Bitmap的存储格式是要以32个位的若干倍存储的,这样当要描画如16×16大小的Bitmap时,就必须要将其扩大成32×32的,这就导致了空间的浪费,OpenGL提供了如下函数可以改变其存储(或解压)格式: glPixelStorei(GL_UNPACK_ALIGNMENT, GLint param ) param可以是1,2,4,8分别表示1,2,4,5字节对齐。 需要注意 Width和height 不需要按照上述说明设置。 26沈阳东软软件股份有限公司 AVNC 事业部
  • 28. 绘制位图、图像(4)绘制图像 void glDrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) Width和height参数说明图像的宽度和高度,以像素为单位。 format指出数据元素格式,常用的主要是GL_RGB,GL_RGBA。 type指出元素数据类型,常用的主要是GL_UNSIGNED_BYTE pixels是指向图象数据的指针。 27沈阳东软软件股份有限公司 AVNC 事业部
  • 29. OpenGL显示列表 OpenGL显示列表(Display List)是由一组预先存储起来的留待以后调用的 OpenGL函数语句组成的,当调用这张显示列表时就依次执行表中所列出的函数 语句。前面内容所举出的例子都是瞬时给出函数命令,则OpenGL瞬时执行相应 的命令,这种绘图方式叫做瞬时方式(immediate mode)。 28沈阳东软软件股份有限公司 AVNC 事业部
  • 30. OpenGL显示列表-创建显示列表 void glNewList(GLuint list,GLenum mode);   说明一个显示列表的开始,其后的OpenGL函数存入显示列表中,直至调用结束表的函数(见下面)。参数list是一个正整数,它标志唯一的显示列表。参数mode的可能值有GL_COMPILE和GL_COMPILE_AND_EXECUTE。若要使后面的函数语句只存入而不执行,则用GL_COMPILE;若要使后面的函数语句存入表中且按瞬时方式执行一次,则用GL_COMPILE_AND_EXECUTE。 void glEndList(void);   标志显示列表的结束。 For example glNewList (1, GL_COMPILE); glColor3f (1.0, 0.0, 0.0); glBegin (GL_TRIANGLES); glVertex2f (0.0, 0.0); glVertex2f (1.0, 0.0); glVertex2f (0.0, 1.0); glEnd (); glEndList (); 29沈阳东软软件股份有限公司 AVNC 事业部
  • 31. OpenGL显示列表-执行显示列表 在建立显示列表以后就可以调用执行显示列表的函数来执行它,并且允许在程序中多次执行同一显示列表,同时也可以与其它函数的瞬时方式混合使用。显示列表执行的函数形式如下:   void glCallList(GLuint list); 执行显示列表。参数list指定被执行的显示列表。显示列表中的函数语句按它们被存放 的顺序依次执行;若list没有定义,则不会产生任何事情。 For example glCallList (1); 30沈阳东软软件股份有限公司 AVNC 事业部
  • 32. OpenGL显示列表-管理显示列表之前,我们使用了一个正整数作为显示列表的索引。但是在实际应用中,一般不采用这种方式,尤其在创建多个显示列表的情况下。如果这样做,则有可能选用某个正在被占用的索引,并且覆盖这个已经存在的显示列表,对程序运行造成危害。为了避免意外删除,可以调用函数glGenList()来产生一个没有用过的显示列表,。此外,在管理显示列表的过程中,还可调用函数glDeleteLists()来删除一个或一个范围内的显示列表。 GLuint glGenList(GLsizei range);   分配range个相邻的未被占用的显示列表索引。这个函数返回的是一个正整数索引值, 它是一组连续空索引的第一个值。返回的索引都标志为空且已被占用,以后再调用这个函数 时不再返回这些索引。若申请索引的指定数目不能满足或range为0则函数返回0。 void glDeleteLists(GLuint list,GLsizei range);   删除一组连续的显示列表,即从参数list所指示的显示列表开始,删除range个显示列 表,并且删除后的这些索引重新有效。若删除一个没有建立的显示列表则忽略删除操作。 当建立一个与已经存在的显示列表索引相同的显示列表时,OpenGL将自动删除旧表。 For example listIndex=glGenLists(1); if(listIndex!=0) { glNewList(listIndex,GL_COMPILE); ... glEndList(); } 31沈阳东软软件股份有限公司 AVNC 事业部
  • 33. OpenGL显示列表-管理显示列表之前,我们使用了一个正整数作为显示列表的索引。但是在实际应用中,一般不采用这种方式,尤其在创建多个显示列表的情况下。如果这样做,则有可能选用某个正在被占用的索引,并且覆盖这个已经存在的显示列表,对程序运行造成危害。为了避免意外删除,可以调用函数glGenList()来产生一个没有用过的显示列表,。此外,在管理显示列表的过程中,还可调用函数glDeleteLists()来删除一个或一个范围内的显示列表。 GLuint glGenList(GLsizei range);   分配range个相邻的未被占用的显示列表索引。这个函数返回的是一个正整数索引值, 它是一组连续空索引的第一个值。返回的索引都标志为空且已被占用,以后再调用这个函数 时不再返回这些索引。若申请索引的指定数目不能满足或range为0则函数返回0。 void glDeleteLists(GLuint list,GLsizei range);   删除一组连续的显示列表,即从参数list所指示的显示列表开始,删除range个显示列 表,并且删除后的这些索引重新有效。若删除一个没有建立的显示列表则忽略删除操作。 当建立一个与已经存在的显示列表索引相同的显示列表时,OpenGL将自动删除旧表。 For example listIndex=glGenLists(1); if(listIndex!=0) { glNewList(listIndex,GL_COMPILE); ... glEndList(); } 32沈阳东软软件股份有限公司 AVNC 事业部
  • 34. Thank you谢谢33沈阳东软软件股份有限公司 AVNC 事业部