由于将缓冲区绑定到目标(如GL_ARRAY_BUFFER
)将修改任何绑定的顶点数组对象的状态,因此安全地写入缓冲区可能会很棘手。最简单的解决方案似乎是使用一个缓冲目标,如GL_COPY_WRITE_BUFFER
,它不影响VAO状态。
void write_buffer(GLint name, int size, const void* data)
{
// error handling omitted for clarity...
glBindBuffer(GL_COPY_WRITE_BUFFER, name);
glBufferData(GL_COPY_WRITE_BUFFER, size, data, GL_STATIC_DRAW);
}
这样做的优点是可以安全调用,而不必考虑当前的OpenGL上下文(假设您正在共享状态)和当前绑定的VAO。
然而,根据glBindBuffer
的OpenGL API参考,缓冲区绑定的初始目标可以用作缓冲区如何内部存储的优化提示:
一旦创建,命名缓冲区对象可以根据需要重新绑定到任何目标。然而,GL实现可能会根据缓冲区对象的初始绑定目标来选择如何优化其存储。
这意味着如果缓冲区name
之前没有绑定到适当的最终目标,则上述函数可能会阻碍优化。
我能想到的避免这种惩罚的唯一方法是在创建后立即手动将缓冲区绑定到所需的目标,然后恢复原始绑定:
GLint create_array_buffer()
{
GLint original, name;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &original);
glGenBuffers(1, &name);
glBindBuffer(GL_ARRAY_BUFFER, name);
glBindBuffer(GL_ARRAY_BUFFER, original);
return name;
}
是否有更好的方法来安全地创建和填充缓冲区(关于vao)?流程应该:
- 保留第一个绑定目标的优化提示
- 不干扰任何绑定VAO的状态
- 不读取状态,改变状态和恢复状态,就像我上面做的
仅绑定GL_ARRAY_BUFFER
不会影响绑定的VAO
。只有在调用glVertexAttribPointer
时,才读取绑定状态并将其放入VAO
。重新绑定GL_ELEMENT_ARRAY_BUFFER
不会影响绑定的VAO
状态。
这意味着您可以自由地更改GL_ARRAY_BUFFER
的绑定,只要您确保在调用glVertexAttribPointer
之前绑定正确的缓冲区。