Tekkaman

导航

 

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

 

posted on 2014-05-30 10:40  Tekkaman  阅读(641)  评论(0编辑  收藏  举报