OpenGL ES 3.0编程指南:第六章. Vertex Attributes, Vertex Arrays, and Buffer Objects---(四)

[TOC]

4. Vertex Array Objects

使用顶点数组对象(VAO),能更进一步提升效率,VAO储存顶点数组(或者顶点缓冲对象)配置的各种状态信息,可以快速切换。实际上,总是有一个激活的VAO,默认情况下,各种操作都是在一个默认的VAO(ID为0)上进行的。

创建一个新的VAO

void glGenVertexArrays (GLsizei n, GLuint * arrays)

  • n : 要创建VAO的数量
  • array : 返回新创建的VAO

绑定VAO

void glBindVertexArray (GLuint v)

  • v : 要绑定的VAO

每个VAO都有一个状态向量,描述所有的顶点缓冲绑定和顶点客户端状态(glBindBuffer, glVertexAttribPointer, glEnableVertexAttribArray, glDisableVertexAttribArray),当通过glBindVertexArray绑定了一个新的VAO时,这些方法对新的VAO产生影响。这样,就可以通过切换不同的VAO来快速切换顶点配置信息。

当一个或多个VAO不再需要时,可以进行删除

void glDeleteVertexArrays (GLsizei n, GLuint * arrays)

  • n : 要删除的VAO数量
  • arrays : 包含要删除的VAO的数组

5. Mapping Buffer Objects

在上文中,我们已经介绍了可以通过glBufferDataglBufferSubData来给缓冲对象加载数据。除此之外,还可以将一个缓冲对象的数据储存映射到应用程序的地址空间。

通过glMapBufferRange方法可以获得一个指向缓冲对象数据储存区的指针,应用程序可以使用这个指针来读取或者更新缓冲对象的内容,然后使用glUnmapBuffer来释放这个指针:

void * glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)

  • target : 可以取值为
    GL_ARRAY_BUFFER
    GL_ELEMENT_ARRAY_BUFFER
    GL_COPY_READ_BUFFER
    GL_COPY_WRITE_BUFFER
    GL_PIXEL_PACK_BUFFER
    GL_PIXEL_UNPACL_BUFFER
    GL_TRANSFORM_FEEDBACK_BUFFER
    GL_UNIFORM_BUFFER
  • offset : 缓冲数据储存的偏移,以字节数表示
  • length : 要进行映射的缓冲数据的字节数量
  • access : 访问标识的位域组合,应用程序应至少声明下列一个标识:

| 标识 | 说明 |
| --- | --- |
| GL_MAP_READ_BIT | 应用程序从返回的指针读取数据|
| GL_MAP_WRITE_BIT | 应用程序从返回的指针写入数据|

同时,应用程序也可以声明下列可选标识:

| 标识 | 说明 |
| --- | --- |
| GL_MAP_INVALIDATE_RANGE_BIT | 表示指定范围内的缓冲区内容可以在返回指针之前由驱动程序放弃。这个标识不能和GL_MAP_READ_BIT共用 |
| GL_MAP_INVALIDATE_BUFFER_BIT | 表示整个缓冲区内容可以在返回指针之前由驱动程序放弃。这个标识不能和GL_MAP_READ_BIT共用 |
| GL_MAP_FLUSH_EXPLICIT_BIT | 表示应用程序将明确地用glFlushMappedBufferRange刷新对映射范围子范围的操作。这个标识必须和GL_MAP_WRITE_BIT共用 |
| GL_MAP_UNSYNCHRONIZED_BIT | 表示驱动程序在返回指针之前不需要等待缓冲对象上的未决操作。如果有未决操作,则未决操作的结果和任何未来的操作都变为未定义 |

GLboolean glUnmapBuffer (GLenum target)

  • target : 必须设为*GL_ARRAY_BUFFER
  • 如果解除映射成功会返回 GL_TRUE。通过glMapBufferRange获得的指针直到映射成功解除后才能再次被使用。

Flushing a Mapped Buffer

有时我们通过glMapBufferRange映射缓冲区对象的一个范围,但只更新这个范围数据的一部分,如果调用glMapBufferRange会刷新全部范围数据,这时可以在进行映射时设置 GL_MAP_FLUSH_EXPLICIT_BIT标志,然后通过 glFlushMappedBufferRange进行修改。

void * glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length)

  • target : 可取值为
    GL_ARRAY_BUFFER
    GL_ELEMENT_ARRAY_BUFFER
    GL_COPY_READ_BUFFER
    GL_COPY_WRITE_BUFFER
    GL_PIXEL_PACK_BUFFER
    GL_PIXEL_UNPACK_BUFFER
    GL_TRANSFORM_FEEDBACK_BUFFER
    GL_UNIFORM_BUFFER
  • offset : 从映射缓冲区起点的偏移量,以字节数来表示
  • length : 要刷新的字节数量
  • 如果应用程序使用了GL_MAP_FLUSH_EXPLICIT_BIT进行映射,但是并没有使用glFlushMappedBufferRange来刷新数据,那么它的内容将是未定义的

6. Coping Buffer Objects

无论是 glBufferData、glBufferSubData 还是 glMapBufferRange,都是应用程序到设备(内存到显存)的数据传输,我们还可以通过glCopyBufferSubData 直接复制缓冲区对象的数据:

void glCopyBufferSubData (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size)

  • readtarget : 要读取的缓冲对象
  • writetarget : 要写入的缓冲对象,readtarget和writetarget都可以取值为(书上写不能取同一值,但是查官方文档二者只要数据不交叉就可以取同一个缓冲对象,不知是不是OpenGL ES的特殊限制)
    GL_ARRAY_BUFFER
    GL_ELEMENT_ARRAY_BUFFER
    GL_COPY_READ_BUFFER
    GL_COPY_WRITE_BUFFER
    GL_PIXEL_PACK_BUFFER
    GL_PIXEL_UNPACK_BUFFER
    GL_TRANSFORM_FEEDBACK_BUFFER
    GL_UNIFORM_BUFFER
  • readoffset : 要读取的缓冲对象的字节偏移量
  • writeoffset : 要写入的缓冲对象的字节偏移量
  • size : 要复制的字节数量

你可能感兴趣的:(OpenGL ES 3.0编程指南:第六章. Vertex Attributes, Vertex Arrays, and Buffer Objects---(四))