【OpenGL顶点数组】
在OpenGL中,所有的几何图元都是由顶点定义的,而每个顶点又有很多属性,如:坐标,颜色,法向量等。如果对每个顶点逐个的调用函数来描述,那么,开销是非常大的。而且不方便对复杂几何体顶点的管理。这里采用了顶点数组的方法,不但便于数据的管理,而且大大减少了函数的调用。
使用顶点数组,需要三个步骤:启用数组,指定数组数据、解引用并渲染。下面分别进行介绍。
1、启用数组
OpenGL共有八个顶点数组可供使用,在使用之前,应该先启用要使用的数组,函数如下:
void glEnableClientState(GLenum array);
其中参数array对应8个顶点数组,分别为:
GL_VERTEX_ARRAY
GL_COLOR_ARRAY
GL_SECONDARY_COLOR_ARRAY
GL_INDEX_ARRAY
GL_NORMAL_ARRAY
GL_FOG_COORDINATE_ARRAY
GL_TEXTURE_COORD_ARRAY
GL_EDGE_FLAG_ARRAY
其中最常用的是前两个,本文就以前两个为例。使用结束后,要关闭数组以释放资源,函数如下:
void glDisableClientState(GLenum array),参数与前面相同。
这里面需要注意的是,每个顶点都对应着这8个数组所对应的属性,也就是说地i个顶点,对应的坐标,颜色等信息,由相对应的数组的第i个元素所描述。
2、指定数组的数据
void glVertexPointer(GLint size,GLenum type,GLsizei stride,const GLvoid* pointer);
其中:
size——每个顶点坐标的数量,必须是2,3或4;
type——指定了数组中坐标的数据类型(GL_SHORT,GL_INT,GL_FLOAT,或GL_DOUBLE);
stride——连续的顶点之间的字节偏移量。如果是0,则顶点是紧密相邻的;
pointer——数组的首地址。
其他数组使用发发与上述函数类似。
举例如下:
static GLint vertices[]={25,25,
100,325,
175,25,
175,325};
static GLfloat colors[]={1.0,0.0,0.0,
0.0,1.0,0.0,
0.0,0.0,1.0,
0.0,1.0,1.0};
glEnableClientState(GL_VERTEX_ARRAY);//启用顶点坐标数组
glEnableClientState(GL_COLOR_ARRAY); //启用顶点颜色数组
glVertexPointer(2,GL_INT,0,vertices);//指定坐标数据
glColorPointer(3,GL_FLOAT,0,colors); //指定颜色数据
通过上述的操作,就定义了四个顶点的坐标和颜色,如:第一个顶点的坐标为[25,25],颜色为红色,依次类推。
也可以将不同类型数组的数据放在同一个数组中,如:
static GLfloat interwind[]={25,25,1.0,0.0,0.0,
100,325,0.0,1.0,0.0,
175,25,0.0,0.0,1.0,
175,325,0.0,1.0,1.0};
glVertexPointer(2,GL_FLOAT,5*sizeof(GLfloat),&interwind[0]);
glColorPointer(3,GL_FLOAT,5*sizeof(GLfloat),&interwind[2]);
这里与上面唯一不同的就是第三个参数,这里面,第三个参数是指本数组中(如坐标数组),两个顶点同类坐标之间的距离(如,两个顶点第一个坐标的距离)。当然,它的值若不是0,那么所乘的系数,一定是大于第一个参数的(如,5大于2)。
3、解引用与渲染
void glArrayElement(GLint ith);
获取第ith个顶点的信息,至于能获得哪些信息,取决于开启了哪些顶点数组。如(接上诉代码):
glBegin(GL_TRIANGLES);
glArrayElement(1);
glArrayElement(2);
glArrayElement(3);
glEnd();
则按照上述定义的第2,3,4(第一个顶点是0)个顶点画三角形,这里需要注意的事,glArrayElement函数只是单纯的引用顶点,必须放在glBegin()和glEnd()之间才有意义。
上述方法适合灵活的调用较少数量的顶点,对于顶点较多的几何元素,可以用下列方法:
void glDrawElements(GLenum mode,GLsizei count,GLenum type,void *indices);
其中:
mode——指定是那种图元,和glBegin()中的参数一样;
count——构建一个图元所需要的顶点个数;
type——indices数组的数据类型,必须是GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT和GL_UNSIGNED_INT中的一个;
indices——图元顶点序列的数组。
效果类似于:
glBegin(mode);
for(i=0;i<count;i++)
glArrayElement(indices[i]);
glEnd();
例如,要用以上定义好的数据画两个三角形:
static GLubyte triangleone[]={0,1,2};
static GLubyte triangletwo[]={1,2,3};
glDrawElements(GL_TRIANGLE,3,GL_UNSIGNED_BYTE,triangleone);
glDrawElements(GL_TRIANGLE,3,GL_UNSIGNED_BYTE,triangletwo);
注意,glDrawElements函数不需要也不能放在glBegin()和glEnd()之间。
void glMultiDrawElements(GLenum mode,GLsizei *count,GLenum type,void **indices,GLsizei primcount);
效果相当于:
for(i=0;i<primcount;i++){
if(count[i]>0)
glDrawElements(mode,count[i],type,indices[i]);
}
其中,indeces定义为GLvoid *indeces[primcount]={描述顶点序列的primcount个数组名};
还有其他的一些函数,在这里不再一一分析,可以参考“红宝书”第二章的内容。
顶点数组为构建复杂图元提供了灵活而有效的解决方案,同时提高了OpenGL程序的执行效率,在以后的变成中,应尽量用顶点数组的方式定义图元,以便熟悉并灵活运用!
参考:http://blog.sina.com.cn/s/blog_505b7d470100rjvo.html