在 OpenGL ES 2 中更新 VBO 的顶点

Posted

技术标签:

【中文标题】在 OpenGL ES 2 中更新 VBO 的顶点【英文标题】:Updating the vertices of a VBO in OpenGL ES 2 【发布时间】:2018-02-08 00:01:21 【问题描述】:

如果我想更改 VBO 的顶点,是否必须重复以下代码中显示的过程,但使用新的顶点数组?

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo);

GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
                    vertexBuffer.capacity() * BYTES_PER_FLOAT,
                    vertexBuffer, GLES20.GL_STATIC_DRAW);

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

或者有没有更好、更有效的方法?我相信每次我想更改顶点时调用上面的代码都不会太理想。我感谢任何答案,谢谢。

【问题讨论】:

【参考方案1】:

如果要更改现有缓冲区对象的数据,则应使用glBufferSubDataglBufferData 为缓冲区对象创建新的数据存储,glBufferSubData 更新缓冲区对象的数据存储。这避免了重新分配数据存储的成本。

见OpenGL ES 2.0 Full Specification, 2.9. BUFFER OBJECTS, page 24:

BufferData 删除任何现有的数据存储,并设置缓冲区的值 对象的状态变量如表...

.....

要修改缓冲区对象的数据存储中包含的部分或全部数据,客户端可以使用命令

void BufferSubData( enum target, intptr offset, sizeiptr size, const void *data );

此外,您应该根据需要设置glBufferDatausage 参数。

见OpenGL ES 2.0 Full Specification, 2.9. BUFFER OBJECTS, page 23:

void BufferData( enum target, sizeiptr size, const void *data, enum usage );

....

usage 被指定为三个枚举值之一,表示数据存储的预期应用程序使用模式。值是:

STATIC_DRAW 数据存储内容将由应用程序指定一次, 并多次用作GL绘图命令的来源。

DYNAMIC_DRAW数据存储内容会被应用反复重新指定,多次作为GL绘图命令的来源。

STREAM_DRAW 数据存储内容将由应用程序指定一次,最多使用几次作为 GL 绘图命令的来源。

【讨论】:

...但要注意更新仍在使用的东西,否则您将获得大多数驱动程序的全部复制成本,即使使用glBufferSubData。见community.arm.com/graphics/b/blog/posts/… @Rabbid76 再次感谢您的帮助。如果顶点要经常更改,您认为是否值得创建 VBO?有没有比使用 VBO 更好的方法? @LAD 常见且现代的方法是使用 VBO。但是你必须关注glBufferData的最后一个参数,它可以是GL_STREAM_DRAWGL_STATIC_DRAWGL_DYNAMIC_DRAW.

以上是关于在 OpenGL ES 2 中更新 VBO 的顶点的主要内容,如果未能解决你的问题,请参考以下文章

Android OpenGL ES 2. 0 VBO 不渲染

iPhone Cheetah 3D OpenGL ES 顶点缓冲对象 (VBO) 示例

OpenGL ES 2.0:似乎无法渲染第二个 VBO?

共享内存架构中的 OpenGL (ES 2.0) VBO 性能

OpenGL ES 1.1:无法转换为 VBO

OpenGL ES 2.0 vbo 白屏