修改OpenGL顶点缓冲区的正确方法是什么?

时间:2013-04-04 21:22:37

标签: opengl

我在OpenGL中设置一个顶点缓冲区,如下所示:

int vboVertexHandle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW);

稍后,如果我想向“vertexData”添加或删除顶点,那么正确的方法是什么?它甚至可能吗?我假设我不能直接修改数组而不将其重新发送到GPU。

如果我修改了vertexData数组,那么再次调用它:

glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_DYNAMIC_DRAW);

...会用新数据覆盖旧缓冲区吗?或者我还必须删除旧的?还有更好的方法吗?

3 个答案:

答案 0 :(得分:28)

调用glBufferData时,会设置任何OpenGL缓冲区对象的大小。也就是说,OpenGL将在glBufferData的第二个参数(未在OP中列出)中分配您指定的内存量。实际上,如果你打电话,例如glBufferData( GL_ARRAY_BUFFER, bufferSize, NULL, GL_DYNAMIC_DRAW );,OpenGL将创建一个{em}未初始化数据的bufferSize字节的缓冲区。

您可以使用glBufferSubDataglMapBuffer或任何其他例程来加载任意数量的数据(最大为缓冲区大小)以传递数据。调整缓冲区大小的唯一方法是使用相同缓冲区ID(从glBufferData返回的值)的新大小调用glGenBuffers

也就是说,您总是可以使用缓冲区中的数据子集(类似于删除顶点),如果使用glDrawElements进行渲染,则可以随机访问缓冲区中的元素。将顶点添加到缓冲区需要分配更大的缓冲区,然后您需要重新加载缓冲区中的所有数据。

答案 1 :(得分:4)

http://www.opengl.org/wiki/GLAPI/glBufferData

  

glBufferData为当前绑定到目标的缓冲区对象创建新的数据存储。任何预先存在的数据存储都将被删除。

这解释了对glBufferData的调用将“重新分配”数据,缓冲区将具有新的大小。所有旧数据都将丢失。如果您只想写入缓冲区的一部分,请改用glBufferSubData

http://www.opengl.org/wiki/GLAPI/glBufferSubData

编辑:glBufferSubData仅在您要替换数据时;要改为调整缓冲区大小,您必须调用glBufferData

此外,您不必先破坏缓冲区并生成新缓冲区。请记住,GLuint只是OpenGL的各种“指针”。它不是实际存储,因此重复使用相同的“指针”(如果你当然没有删除它)是完全没错的。

答案 2 :(得分:0)

1通过使用glMapBuffer

void mapBuffer(uint &id, void *data, uint size, uint type) {
    glBindBuffer(type, id);
    // get pointer
    void *ptr = glMapBuffer(type, GL_WRITE_ONLY);
    // now copy data into memory
    memcpy(ptr, data, size);
    // make sure to tell OpenGL we're done with the pointer
    glUnmapBuffer(type);
}

2通过使用glBufferSubData

 void updateBuffer(uint &id, uint offset, void *data, uint size, uint type) {
        glBindBuffer(type, id);
        glBufferSubData(type, offset, size, data);
    }

如果您希望您也可以使用 glBufferData->但它会删除所有旧数据并重用同一缓冲区 glInvalidateBufferSubData->在所有位置都放置NULL,现在您可以输入自己的数据了。