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

nbnkbykc  于 2022-09-26  发布在  其他
关注(0)|答案(3)|浏览(182)

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

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

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

如果我修改vertex Data数组,则再次调用此函数:

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

...这会用我的新数据覆盖旧缓冲区吗?或者,我还需要删除旧的吗?有没有更好的办法?

ix0qys7i

ix0qys7i1#

任何OpenGL缓冲区对象的大小都是在调用glBufferData时设置的。也就是说,OpenGL将分配您在glBufferData的第二个参数中指定的内存量(它没有在op中列出)。事实上,如果调用,例如glBufferData( GL_ARRAY_BUFFER, bufferSize, NULL, GL_DYNAMIC_DRAW ); OpenGL将创建一个包含未初始化数据bufferSize字节的缓冲区。

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

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

lskq00tm

lskq00tm2#

http://www.opengl.org/wiki/GLAPI/glBufferData
GLBufferData为当前绑定到目标​的缓冲区对象创建新的数据存储。任何先前存在的数据存储都将被删除。

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

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

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

而且,您不必首先销毁缓冲区并生成新的缓冲区。请记住,GLuint只是OpenGL的一种“指针”。它不是实际的存储,因此完全可以重复使用相同的“指针”(当然,如果您还没有删除它的话)。

5uzkadbs

5uzkadbs3#

%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);
    }

指定要替换的数据存储区域的大小(以字节为单位

mapBuffer(vbo, vertex.data(), sizeof(uint)*vertex.size(), GL_ARRAY_BUFFER);
resetBuffer(vbo, vertex.data(), sizeof(uint)*vertex.size(), GL_ARRAY_BUFFER);
updateBuffer(vbo, 0, vertex.data(), sizeof(uint)*vertex.size(), GL_ARRAY_BUFFER);

如果你想要,你也可以使用glBufferData->,但是它删除了所有的旧数据并重新使用了相同的缓冲区glInvalidateBufferSubData->它在所有地方都放了NULL,现在你可以提供你自己的数据了。

相关问题