我在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);
...会用新数据覆盖旧缓冲区吗?或者我还必须删除旧的?还有更好的方法吗?
答案 0 :(得分:28)
调用glBufferData
时,会设置任何OpenGL缓冲区对象的大小。也就是说,OpenGL将在glBufferData
的第二个参数(未在OP中列出)中分配您指定的内存量。实际上,如果你打电话,例如glBufferData( GL_ARRAY_BUFFER, bufferSize, NULL, GL_DYNAMIC_DRAW );
,OpenGL将创建一个{em}未初始化数据的bufferSize
字节的缓冲区。
您可以使用glBufferSubData
,glMapBuffer
或任何其他例程来加载任意数量的数据(最大为缓冲区大小)以传递数据。调整缓冲区大小的唯一方法是使用相同缓冲区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,现在您可以输入自己的数据了。