OpenGL:VAO/VBO 混淆

Posted

技术标签:

【中文标题】OpenGL:VAO/VBO 混淆【英文标题】:OpenGL: VAO/VBO confusion 【发布时间】:2014-01-03 15:24:07 【问题描述】:

OpenGL Wiki: Vertex Specification 声明:

注意:GL_ARRAY_BUFFER​ 绑定是不是 VAO 状态的一部分!我知道这很令人困惑,但事实就是如此。

以下是我如何使用 VAO,它似乎按预期工作。这里有什么问题?我对 OpenGL(或 OpenGL Wiki)、我的 OpenGL 驱动程序 (OSX 10.9) 或 OpenGL Wiki 的理解?

// ------ Pseudo-code ------ 
// setup
[...]
glBindVertexArray(vertexArrayObjectIdx1);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferId1);
for each vertex attribute
    glEnableVertexAttribArray(...);
    glVertexAttribPointer(...);

glBindVertexArray(vertexArrayObjectIdx2);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferId2);
for each vertex attribute
    glEnableVertexAttribArray(...);
    glVertexAttribPointer(...);

// rendering
[...]
glBindVertexArray(vertexArrayObjectIdx1);
glDrawElements(...);
glBindVertexArray(vertexArrayObjectIdx2);
glDrawElements(...);

【问题讨论】:

【参考方案1】:

这意味着当你重新绑定VAOGL_ARRAY_BUFFER不会反弹

但是,glVertexAttribPointer 确实将(当时)绑定的GL_ARRAY_BUFFER 绑定到了 VAO 中的正确属性,因此它可以按您的意愿工作。

实际上他们可以将glVertexAttribPointer 定义为:

void glVertexAttribPointer(GLuint index​, GLint size​, GLenum type​, GLboolean normalized​, GLsizei stride​, uint bufferName, const GLvoid * pointer​);

并消除它对绑定GL_ARRAY_BUFFER 的依赖。但事后诸葛亮……

重要的是要记住GL_ARRAY_BUFFER对于绘图并不重要,但顶点属性的绑定方式很重要。

相比之下,GL_ELEMENT_ARRAY_BUFFER 存储在 VAO 中

【讨论】:

实际上有一个glVertexAttribPointer (...) 的版本,其签名大致相同。但是你必须使用Direct State Access 扩展(它基本上排除了Apple、Intel 和Mesa 的实现,只留下了AMD 和NV)。 非常 一开始你会觉得很尴尬(主要是因为函数名),但是这个丑陋的函数:glVertexArrayVertexAttribOffsetEXT (...) 会让你设置一个指向 VBO 的数据存储的指针,指向特定索引处的 VAO,而不绑定 VBO 或 VAO。 也就是说,他们真的不能那样定义glVertexAttribPointer (...),因为这个函数是通过ARB顶点程序扩展引入OpenGL的。并且 ARBVP1 可以在没有顶点缓冲区对象的情况下实现(ARBVP1 比 VBO 早 2-3 年)。 @AndonM.Coleman 不否认,如果他们可以从头开始重新设计,那么他们将大大减少对全局状态的依赖 当然会。我只是指出 glVertexAttribPointer (...) 最初并不是这样设计的,因为当着色器首次引入 OpenGL 时 VBO 并不存在。 Long's Peak 会让 OpenGL 成为一个更好的 API,但我们剩下的只是 DSA 扩展,它没有得到广泛支持:(【参考方案2】:

在同一个 Wiki 条目的下方,您也可以看到解释 - This is also why GL_ARRAY_BUFFER​ is not VAO state; the actual association between an attribute index and a buffer is made by glVertexAttribPointer​. ...

【讨论】:

以上是关于OpenGL:VAO/VBO 混淆的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:一个 VBO 的多个 VAO

使用 VAO/VBO 进行 OpenGL 模型/纹理渲染

openGL中vao/vbo的debug经历

两个不同的对象 OpenGL。 VAO VBO IBO 网格变形问题

VAO VBO EBO

使用 VAO 在 OpenGL 中更改绘制的实例化顺序