您的位置:首页 > 运维架构

OPENGL顶点数组, glDrawArrays,glDrawElements

2014-08-14 16:38 405 查看
顶点数组, glDrawArrays,glDrawElements

前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接下来看看这些函数是如何使用的。

1.glEnableClientState(GL_VERTEX_ARRAY); 使能顶点数组功能。

2.将准备好的数组告知程序,使用glVertexPointer(),原型如下:

void glVertexPointer(

GLint size, //每个顶点占用的数组元素数量

GLenum type, //数组元素的数据类型

GLsizei stride, //元素之间的间隔,一般系统为0

const GLvoid *pointer //指向数组的指针

);

3.进行绘图:glDrawArrays()或者 glDrawElements(),glDrawElements()主要用于索引数组。函数原型如下:

void glDrawArrays(

GLenum mode, //绘图方式 GL_POINTS、GL_QUADS etc

GLint first, //第一个元素的下标

GLsizei count //绘制元素的数量

);

void glDrawElements(

GLenum mode, //绘图方式 GL_POINTS、GL_QUADS etc

GLsizei count, //顶点数组当中元素的个数

GLenum type, //索引数组当中元素数据类型

const GLvoid *indices //指向索引数组的指针

);

对应于顶点数组,OpenGL当中还提供了法向量数组、纹理坐标数组等等的支持,这些数组与顶点数组的使用方式相同,只是在相关参数和函数名称上将Vertex改为对应的名字即可。

glEnableClientState(GL_COLOR_ARRAY);

glColorPointer();

glDrawArrays 和 glDrawElements 的作用都是从一个数据数组中提取数据渲染基本图元。(
render primitives from array data )





注!如果要 glDrawArrays 和 glDrawElements 正确进行绘制的话,必须在之前 调用带有相应参数的 glEnableClientState 方法。 比如:

glEnableClientState( GL_VERTEX_ARRAY );

glEnableClientState( GL_TEXTURE_COORD_ARRAY );

这两个方法的第一个形参都是代表 绘制模式(GLenum mode)。绘图模式有如下几种:

GL_POINTS

GL_LINES

GL_LINE_LOOP

GL_LINE_STRIP

GL_TRIANGLES

GL_TRIANGLE_STRIP

GL_TRIANGLE_FAN




我们还没有讨论点或线,所以我只介绍最后的三个 。

在我开始之前,我要提醒你,顶点数组可能包含不止一个三角形,以便当您只看到一个物体顶点数组,你要知道,不仅限于这一点。



假设我们有如下的顶点数据:

const GLfloat
 squareVertices[] = {

    -1.0,  1.0, -6.0, //
 Top left

    -1.0, -1.0, -6.0, //
 Bottom left

    1.0,  -1.0, -6.0, //
 Bottom right

    1.0,   1.0, -6.0  //
 Top right

};

GL_POINTS - 单独的将顶点画出来。



GL_LINES -
单独地将直线画出来。行为和 GL_TRIANGLES 类似。

GL_LINE_STRIP - 连贯地将直线画出来。行为和 GL_TRIANGLE_STRIP 类似。



GL_LINE_LOOP - 连贯地将直线画出来。行为和 GL_LINE_STRIP 类似,但是会自动将最后一个顶点和第一个顶点通过直线连接起来。



GL_TRIANGLES - 这个参数意味着OpenGL使用三个顶点来组成图形。所以,在开始的三个顶点,将用顶点1,顶点2,顶点3来组成一个三角形。完成后,在用下一组的三个顶点(顶点4,5,6)来组成三角形,直到数组结束。



GL_TRIANGLE_STRIP - OpenGL的使用将最开始的两个顶点出发,然后遍历每个顶点,这些顶点将使用前2个顶点一起组成一个三角形。

所以 squareVertices[6~8]{1.0, -1.0, 6.0} 将与 squareVerticies[0~2]{-1.0, 1.0, -6.0} 和 squareVerticies[3~5]{-1.0, -1.0, -6.0} 生成一个三角形。

squareVertices[9~11]{1.0, 1,0, -6.0} 将与 squareVertices[3~5]{-1.0, -1.0, -6.0} 和squareVertices[6~8]{1.0, -1.0, 6.0} 生成三角形。



也就是说,P0,P1,P2这三个点组成一个三角形,P1,P2,P3这三个点也组成一个三角形。



注意的是, squareVerticies[0~2]表示的意思是:

squareVerticies[0] x坐标

squareVerticies[1] y坐标

squareVerticies[2] z坐标





GL_TRIANGLE_FAN - 在跳过开始的2个顶点,然后遍历每个顶点,让OpenGL将这些顶点于它们前一个,以及数组的第一个顶点一起组成一个三角形。 squareVertices[6~8]{1.0,
-1.0, 6.0} 将与 squareVerticies[3~5]{-1.0, -1.0, -6.0} (前一个)和 squareVerticies[0~2]{-1.0, 1.0, -6.0}(第一个).生成一个三角形。



也就是说,同样是P0,P1,P2,P3 这4个顶点。

1) 在 GL_TRIANGLE_STRIP 状态下是: P2、P1、P0 ; P3、P2、P1 这2个三角形。

2) 在 GL_TRIANGLE_FAN 状态下是: P2、P1、P0 ; P3、P2、P0 这2个三角形。








1.1 glDrawArrays 方法介绍



Description

glDrawArrays specifies multiple geometric primitives with very few subroutine calls. You can prespecify separate arrays of vertices, normals, colors, and texture coordinates
and use them to construct a sequence of primitives with a single call to glDrawArrays.



When glDrawArrays is called, it uses count sequential elements from each enabled array to construct a sequence of geometric primitives, beginning with element first. mode specifies
what kind of primitives are constructed, and how the array elements construct those primitives. If GL_VERTEX_ARRAY is not enabled, no geometric primitives are generated.



Vertex attributes that are modified by glDrawArrays have an unspecified value after glDrawArrays returns. For example, if GL_COLOR_ARRAY is enabled, the value of the current
color is undefined after glDrawArrays executes. Attributes that aren't modified remain well defined.

示例代码:

glEnableClientState(GL_VERTEX_ARRAY);

    

const GLfixed vers[] = {

        F2X(0.25), F2X(0.25), F2X(0.0), 

        F2X(0.75), F2X(0.25), F2X(0.0), 

        F2X(0.25), F2X(0.75), F2X(0.0), 

        F2X(0.75), F2X(0.75), F2X(0.0), 

};
glVertexPointer(3, GL_FIXED, 0, vers);

    

glDrawArrays(GL_LINE_STRIP, 0, 4);

    

eglSwapBuffers(iGlDisp, iGlSurface);

结果:







1.2 glDrawElements 是一个OPENGL的图元绘制函数,从数组中获得数据并渲染图元。

函数原型为:

void glDrawElements(

GLenum mode,

GLsizei count,

GLenum type,

const GLvoid *indices

);

其中:

mode 指定绘制图元的类型,但是如果GL_VERTEX_ARRAY 没有被激活的话,不能生成任何图元。它应该是下列值之一:

GL_POINTS, GL_LINE_STRIP,

GL_LINE_LOOP, GL_LINES,

GL_TRIANGLE_STRIP,

GL_TRIANGLE_FAN,

GL_TRIANGLES,

GL_QUAD_STRIP,

GL_QUADS,

GL_POLYGON



count 为绘制图元的数量。

type 为索引数组(indices)中元素的类型,只能是下列值之一:

GL_UNSIGNED_BYTE,

GL_UNSIGNED_SHORT,

GL_UNSIGNED_INT



indices:指向索引数组的指针。

glDrawElements函数能够通过较少的函数调用绘制多个几何图元,而不是通过OPENGL函数调用来传递每一个顶点,法线,颜色信息。



你可以事先准备一系列分离的顶点、法线、颜色数组,并且调用一次glDrawElements把这些数组定义成一个图元序列。



当调用glDrawElements函数的时候,它将通过索引使用count个成序列的元素来创建一系列的几何图元。



glDrawElements修改的顶点属性在glDrawElements调用返回后的值具有不确定性。

例如,在 GL_COLOR_ARRAY 被激活后,当glDrawElements执行完成时,当前的颜色值是没有指定的。没有被修改的属性值保持不变。



可以在显示列表中包含 glDrawElements,当glDrawElements被包含进显示列表时,相应的顶点、法线、颜色数组数据也得进入显示列表的,因为那些数组指针是ClientSideState的变量,在显示列表创建的时候而不是在显示列表执行的时候,这些数组指针的值影响显示列表。



glDrawElements 只能用在 OPENGL1.1 或者更高的版本。

示例代码如下:

// The vertex array is enabled
 for writing and used during rendering.

glEnableClientState(GL_VERTEX_ARRAY); 

// 顶点坐标数组

const GLfixed vers[] = {

        F2X(0.25), F2X(0.25), F2X(0.0), //
 第1个顶点坐标

        F2X(0.75), F2X(0.25), F2X(0.0), //
 第2个顶点坐标

        F2X(0.25), F2X(0.75), F2X(0.0), //
 第3个顶点坐标

        F2X(0.75), F2X(0.75), F2X(0.0)  //
 第4个顶点坐标

};

glVertexPointer(

        3,        //
 表示每一个顶点由3维坐标构成

        GL_FIXED, //
 顶点坐标数组中的元素是 GL_FIXED 类型

        0,        //
 从顶点坐标数组的第0个元素开始读取数据

        vers      // 指向顶点坐标数组的指针

        );

// 等效替换 glDrawArrays(GL_TRIANGLE_STRIP,
 0, 4) ++

const GLubyte indices[] = {0, 1, 2, 3};

glDrawElements(

        GL_TRIANGLE_STRIP, //
 绘图模式

        4,                 //
 依次从索引数组中读取4个顶点来进行绘制

        GL_UNSIGNED_BYTE,  //
 索引数组中存放的元素的类型

        indices            //
 指向索引数组的指针

        );

//
 等效替换 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) --

eglSwapBuffers(iGlDisp, iGlSurface);

#SinaEditor_Temp_FontName

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: