美文网首页程序员今日看点
OpenGL ES 3.0编程指南:第七章. Primitive

OpenGL ES 3.0编程指南:第七章. Primitive

作者: 别卡机 | 来源:发表于2016-10-19 17:29 被阅读429次

2. Drawing Primitives

在OpenGL ES中,有5种绘制图元的方法:glDrawArrays, glDrawElements, glDrawRangeElements, glDrawArraysInstanced, glDrawElementsInstanced

void glDrawArrays (GLenum mode, GLint first, GLsizei count)

  • mode : 绘制的图元类型,可取值为
    GL_POINTS
    GL_LINES
    GL_LINE_STRIP
    GL_LINE_LOOP
    GL_TRIANGLES
    GL_TRIANGLE_STRIP
    GL_TRIANGLE_FAN
  • first : 起始顶点索引
  • count : 要绘制的顶点数量

void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
void glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices)

  • mode : 绘制的图元类型,可取值为
    GL_POINTS
    GL_LINES
    GL_LINE_STRIP
    GL_LINE_LOOP
    GL_TRIANGLES
    GL_TRIANGLE_STRIP
    GL_TRIANGLE_FAN
  • start : 指明indices中最小的顶点索引
  • end : 指明indices中最大的顶点索引
  • count : 要绘制的顶点数量
  • type : 指明indices中储存的元素索引类型,可取值为
    GL_UNSIGNED_BYTE
    GL_UNSIGNED_SHORT
    GL_UNSIGNED_INT
  • indices : 指向元素索引储存的位置

如果图元的顶点索引是连续的,并且顶点不共享,那么可以用glDrawArrays。但是大多数情况下,顶点索引不是连续的,并且顶点是共享的,比如正方体,这时,用glDrawElements比较好。比如:


如果用glDrawArrays的话,需要声明24个(用GL_TRIANGLE_FAN)或者36个(用GL_TRIANGLE)顶点数据,而实际上正方体只有8个顶点:
#define VERTEX_POS_INDEX 0
#define NUM_FACES 6

GLfloat vertices[] = {...};
glEnableVertexAttribArray (VERTEX_POS_INDEX);
glVertexAttribPointer (VERTEX_POS_INDEX, 3, GL_FLOAT, GL_FALSE, 0, vertices);

for (int i=0; i < NUM_FACES; i++)
{
    glDrawArrays (GL_TRIANGLE_FAN, i*4, 4);
}
        or
glDrawArrays (GL_TRIANGLES, 0, 36);

如果用glDrawElements的话:

#define VERTEX_POS_INDEX 0
GLfloat vertices[] = {...}
GLubyte indices[36] = {0, 1, 2, 0, 2, 3,
   0, 3, 4, 0, 4, 5,
   0, 5, 6, 0, 6, 1,
   7, 1, 6, 7, 2, 1,
   7, 5, 4, 7, 6, 5,
   7, 3, 2, 7, 4, 3};
glEnableVertexAttribArray (VERTEX_POS_INDEX);
glVertexAttribPointer (VERTEX_POS_INDEX, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawElements (GL_TRIANGLES, sizeof(indices)/sizeof(GLubyte), GL_UNSIGNED_BYTE, indices);

Primitive Restart

使用图元重启, 可以在 glDrawElementsXXX 绘制方法中,通过一次命令绘制多个不相连的图元(如 triangle stripes or triangle fans)。
在索引列表中,通过插入一个特殊索引来重启一个绘制调用,这个索引是该索引类型的最大值,比如 GL_UNSIGNED_BYTE的255。
举例:绘制两条三角形条带的索引分别为(0,1,2,3)和(8,9,10,11),那么一次绘制调用的索引为(0,1,2,3,255,8,9,10,11)。

启用和关闭图元索引的方法:

glEnable (GL_PRIMITIVE_RESTART_FIXED_INDEX);
glDisable (GL_PRIMITIVE_RESTART_FIXED_INDEX);

Provoking Vertex

Vertex Shader的输出值默认使用线性插值,但是当用 flat 修饰输出变量时,不进行插值,这时只有一个顶点值能被 Fragment Shader使用,驱动顶点决定了哪一个顶点值被使用。


Geometry Instancing

几何图形实例化允许只调用一次API,就可以高效地多次绘制具有不同属性的物体,适合同时绘制大量相似的物体。它降低了向OpenGL ES引擎发送许多API调用的CPU处理开销,因此能够提高效率。

void glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
void glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei instanceCount)

  • mode : 绘制的图元类型,可取值为
    GL_POINTS
    GL_LINES
    GL_LINE_STRIP
    GL_LINE_LOOP
    GL_TRIANGLES
    GL_TRIANGLE_STRIP
    GL_TRIANGLE_FAN
  • first : 起始顶点索引
  • count : 要绘制的顶点数量
  • type : 指明indices中储存的元素索引类型,可取值为
    GL_UNSIGNED_BYTE
    GL_UNSIGNED_SHORT
    GL_UNSIGNED_INT
  • indices : 指向元素索引储存的位置
  • instanceCount : 要绘制的实例数量

有两种方法可以访问每个实例的数据:

  • 通过 glVertexAttribDivisor 方法:

void glVertexAttribDivisor (GLuint index, GLuint divisor)

  • index : 顶点属性索引
  • divisor : 指定index位置的属性更新之间传递的实例数量
  • 当没有使用 glVertexAttribDivisor 或者 divisor为0时,对每个顶点读取一次顶点属性。如果 divisor 为 1, 则每个图元实例读取一次顶点属性(逐实例读取一个顶点属性)。
  • 通过内建变量 gl_InstanceID 作为 缓存区索引来访问。当使用几何图形实例化API时,gl_InstanceID将保存当前图元实例的索引,如果使用的是非几何图形实例化API,gl_InstanceID的值为0 。

Performance Tips

用 glDrawElements* 绘制时,应尽可能的多绘制图元,比如通过 Primitive Start 将两个不相连的图元一次绘制出来,当无法使用 Primivite Start 时,可以使用添加顶点索引生成退化三角形来一次绘制多个图元,退化三角形是指有顶点相同的三角形,GPU可以轻易的检测并拒绝这些退化三角形。

当添加退化三角形顶点索引时,需要检查要连接的两个图元的最后一个三角形片段和第一个三角形片段,说明如下:


  • 第一个三角形图元的奇数下标编号三角形片段 与 第二个三角形图元的第一个三角形片段(很明显是偶数下标编号“0”)相连。两个三角形图元的顶点索引分别是(0,1,2,3)和(8,9,10,11),那么调用 glDrawElements* 时传入的参数列表就是(0,1,2,3,***3,8 *** ,8,9,10,11)
  • 第一个三角形图元的偶数下标编号三角形片段 与 第二个三角形图元的第一个三角形片段(很明显是偶数下标编号“0”)相连。两个三角形图元的顶点索引分别是(0,1,2,3,4)和(8,9,10,11),那么调用 glDrawElements* 时传入的参数列表就是(0,1,2,3,4,4,4,8,8,9,10,11)

相关文章

网友评论

    本文标题:OpenGL ES 3.0编程指南:第七章. Primitive

    本文链接:https://www.haomeiwen.com/subject/wcvxuttx.html