您需要通过为它们调用glDeleteBuffers() 来明确删除所有VBO。
您最好的选择是真正保留您生成的 VBO id,并在不再需要它们时将其删除,这通常与您删除 VAO 的时间差不多。除非 VBO 中的数据是完全静态的,否则您通常仍需要它们的 id,以便您可以绑定它们,并使用 glBufferSubData() 之类的调用更新它们的数据。
要获取当前绑定的 VAO 的 VBO id,您可以使用 glGetVertexAttribiv()。要枚举所有这些,代码如下所示:
GLint nAttr = 0;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nAttrib);
glBindVertexArray(vaoId);
for (int iAttr = 0; iAttr < nAttr; ++iAttr) {
GLint vboId = 0;
glGetVertexAttribiv(iAttr, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vboId);
if (vboId > 0) {
...
}
}
使用它删除 VBO 时必须小心,因为同一个 VBO 可能会绑定多个属性。因此,您必须首先创建一个唯一 ID 列表,例如将它们放入std::set。如果您将同一个 VBO 用于多个 VAO,那就更麻烦了,这当然是完全合法的,也很常见。
为了完整起见,我还要提到一个选项。我不建议这样做。这依赖于这样一个事实,即只要 VBO 绑定到 VAO 中的属性,它就会保持活动状态。因此,理论上,您可以在用数据填充 VBO 并将它们绑定到 VAO 属性后,在 VBO 上调用 glDeleteBuffers()。虽然删除它们后它们的 id 将无效,但数据将保持有效,直到最后一个引用缓冲区的 VAO 被删除。
最后一种方法的某些方面让你很容易在脚下开枪。如果您正在认真考虑使用它,则应仔细阅读 GL 4.4 规范第 5.1.3 节中以“删除附加到容器对象的对象时应小心”开头的段落,或附录 D 中的相同内容.1.2 在 GL 3.3 规范中。