浅谈怎样使用OpenGL绘制简单二维图形

  • 格式:pdf
  • 大小:189.13 KB
  • 文档页数:4

浅谈怎样使用OpenGL绘制简单二维图形
摘要:在上一章节中我们讲解了OpenGL的基本原理,以及怎样在MFC中配置OpenGL 绘图环境,而在这一章节我开始正式绘图(注意上一章节的内容严格的来讲是属于window 编程,而不属于OpenGL)。

我们先从一个简单例子开始讲解:绘制一个在视图中央,长宽各为视图长宽一半的矩形。

1.1 视图设置
与GDI二维函数库不同,OpenGL是一套三维绘图函数库。

使用GDI时,点的坐标对应的就是像素点坐标(已窗口左上角为(0,0)点),而OpenGL绘图时使用的是顶点坐标,要通过一系列转换最终换算成窗口的像素坐标,这种转换就是视图的设置,视图设置将在第三章详细讲解,本章只使用最简单的一种视图设置——2D正投影。

(视图设置的详细内容将在下一章讲解)
设置2D正投影所需的函数如下:
glMatrixMode(GL_PROJECTION);
将投影矩阵设置为当前矩阵(后续设置矩阵的函数都是对投影矩阵起作用)
glLoadIdentity();
将当前矩阵设置为单位矩阵
gluOrtho2D(left,right,bottom,top);
创建一个把二维坐标投影到屏幕上的矩阵,并把当前矩阵与它相乘。

裁剪区域为矩形,它的左下坐标为(left,bottom),右上坐标为(right,top)。

glViewport(x,y,width,height);
在窗口中定义一个像素矩形,最终的图像将映射到这个矩形中。

(x,y)参数指定了视口的左下角,width和height表示这个视口矩形的宽度和高度。

在默认情况下,视口的初始值是(0,0,winWidth,winHeight),其中winWidth和winHeight为对应窗口的大小。

在2D正投影模式下,OpenGL坐标于窗口显示的坐标对应逻辑如图 1 窗口映射关系所示:
图 1 窗口映射关系
1.2 绘制几何图元
设置完视图和投影模式之后,我们便可以开始绘图了,但在这之前还要注意清空视图,防止绘图效果累加,比如要画一个移动圆形,如果不将前一帧的绘图擦除,我们将看到的是一系列的圆形,而不是一个移动的圆形,这和使用GDI在每次绘图都要用背景将上一次的绘图效果覆盖一样。

在OpenGL中,擦除原有视图只需调用函数:
glClearColor(1.0,1.0,1.0,1.0f); //设置用于擦除的颜色,此例中使用的是白色
glClear(GL_COLOR_BUFFER_BIT); //擦除颜色缓冲区
OpenGL绘制几何图元的基本格式如下:
glBegin(GLenum mode /*几何图元类型*/); //开始绘制几何图元
glVertex2f( GLfloat x, GLfloat y); //设置此几何图元所包含的所有顶点坐标
glVertex2f( GLfloat x, GLfloat y);
······
glEnd(); //结束绘制几何图元
几何图元的类型和绘制效果如图 2 几何图元类型所示
图 2 几何图元类型
1.3 顶点数组
通过上一章节,我们知道OpenGL需要进行大量的函数调用才能完成对几何图元的渲染。

如绘制一条由2000个点相连的曲线,至少需要2002个函数调用。

首先调用1次glBegin(),然后为每个顶点调用1次函数glVertex2f,最后调用一次glEnd()。

函数调用本身就有一定的资源开销,如此多得函数调用必然会影响程序性能。

OpenGL提供了一些顶点数组函数,允许只用少数几个数组指定大量的与顶点相关的数据,并用少量的函数调用访问这些数据。

使用顶点数组对几何图形进行渲染需要3个步骤
1)激活(启用)最多可达8个数组,每个数组用于存储不同类型的数据:顶点坐标,表面法线,RGBA颜色,辅助颜色,颜色索引,雾坐标,纹理坐标以及多边形的边界
标志。

(本章只介绍顶点数组)
2)把数据放入数组中。

这些数组是通过它们的内存位置的地址(即指针)进行访问的。

3)用这些数据绘制几何图形
1.3.1 步骤1:启用数组
第一个步骤是调用glEnableClientState(GLenum cap)激活选择的数组,其参数是枚举值,表示要启用哪个数组,其值可以为
GL_VERTEX_ARRAY,//顶点坐标
GL_NORMAL_ARRAY, //表面法线
GL_COLOR_ARRAY, //RGBA颜色
GL_SECONDARY_COLOR_ARRAY,//辅助颜色
GL_INDEX_ARRAY, //颜色索引
GL_FOG_COORD_ARRAY, //雾坐标
GL_TEXTURE_COORD_ARRAY,//纹理坐标
GL_EDGE_FLAG_ARRAY, //多边形的边界标志
注意GL_COLOR_ARRAY数组和GL_INDEX_ARRAY不能同时启用
在使用完数组后要关闭相关数组,防止资源浪费。

为此,可以调用函数
glDisableClientState(GLenum cap)
1.3.2 步骤2:指定数组的数据
在启用了数组之后,边可以给数组指定数据了。

每个数组都有其对应的函数,这里只介绍设置顶点坐标数组的函数:
void glVertexPointer( Glint size, GLenum type, GLsizei stride, const GLvoid * pointer);
参数意义
size:每个顶点的坐标数量,它必须是2,3,或4。

type:指定数据的数据类型,如GL_FLOAT,GL_INT。

stride:连续顶点之间的字节偏移量,如果值为0,表示数组中的顶点是紧密相邻的pointer:数据指针
1.3.3 步骤3:解引用和渲染
指定完数组的数据,就可以使用这些数据绘图了,调用函数:
glDrawArrays (GLenum mode, GLint first, GLsizei count);
参数意义
mode:要绘制的几何图元类型,如GL_LINES,GL_POINTS
first:要使用的数组元素起点
count:要使用的数组元素个数
1.4 OpenGL函数的语法
OpenGL所有函数都使用前缀“gl”,并把组成函数的每个单词的首写字母用大写形式表示(例如:glClearColor())。

类似的,OpenGL还定义了一些以前缀GL_开头的常量,所有的单词都使用大写形式,并以下划线分隔(例如GL_COLOR_BUFFER_BIT)OpenGL很多函数都有表示其参数个数和类型的后缀,如glVertex3f(),后缀为“3f”,其中“3”表示这个函数有三个参数,“f”表示所有参数的类型为32位浮点。

后缀中的字符与类型的相对关系如下表所示。

表1 函数后缀和参数数据类型。