调用 glDeleteVertexArrays 后是否可以通过稍后调用 glGenVertexArrays 重新使用 VAO 名称?

Can a VAO name be re-used after calling glDeleteVertexArrays by calling glGenVertexArrays later?

我从 OpenGL 文档中了解到,可以删除 VAO (glDeleteVertexArrays),然后重新生成 (glGenVertexArrays)。但是,当我尝试在 Chunk class(对于 Minecraft 克隆)中重新使用现有 VAO 变量时遇到 OpenGL 错误时,我遇到了一个问题。这只发生在某些块上,我不明白为什么。我输出了 VAO 值(unsigned int 类型),用 glDeleteVertexArrays 删除后它似乎没有改变。我从文档中了解到,在 运行 此函数之后,此值将重置为零。请参阅下面的块 class 代码。

void Chunk::load()
{
    // Update chunk state
    loaded = true;

    // Set up OpenGL buffers
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &vertexVBO);
    glGenBuffers(1, &textureVBO);
    glGenBuffers(1, &EBO);
    
    // VAO bound before setting up buffer data
    glBindVertexArray(VAO);
    // Indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
                 indices.size() * sizeof(unsigned int), 
                 &indices[0], 
                 GL_DYNAMIC_DRAW);
    // Vertices
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
    glBufferData(GL_ARRAY_BUFFER, 
                 vertices.size() * sizeof(float), 
                 &vertices[0], 
                 GL_DYNAMIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(unsigned int), (void*)0);
    glEnableVertexAttribArray(0);
    // Texture Coordinates
    glBindBuffer(GL_ARRAY_BUFFER, textureVBO);
    glBufferData(GL_ARRAY_BUFFER, 
                 texCoords.size() * sizeof(float), 
                 &texCoords[0], 
                 GL_DYNAMIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    
    // Unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
void Chunk::unload()
{
    // Update chunk state
    loaded = false;

    // Delete arrays/buffers.
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &vertexVBO);
    glDeleteBuffers(1, &textureVBO);
    glDeleteBuffers(1, &EBO);
}

正如 C++ 中的 delete ptr; 或 C 中的 free(ptr); 实际上不会改变 ptr 变量的指针值一样,在 OpenGL 对象上调用 glDelete* 也不会改变你给它的变量的值。是否再次使用该变量或将其分配给中性值取决于您。

话虽如此,如果您打算立即创建一个新的 VAO...何必呢?只需通过禁用所有属性数组和缓冲区绑定来清除旧的,它就可以重新使用了:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

GLint maxAttrib;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrib);

for(int attribIx = 0; attribIx < maxAttrib; ++attribIx)
{
  glDisableVertexAttribArray(attribIx);
  glVertexAttribPointer(attribIx, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
  glVertexAttribDivisor(attribIx, 0);
}