为啥 OpenGL 缓冲区解除绑定顺序很重要? [复制]

Posted

技术标签:

【中文标题】为啥 OpenGL 缓冲区解除绑定顺序很重要? [复制]【英文标题】:Why does OpenGL buffer unbinding order matter? [duplicate]为什么 OpenGL 缓冲区解除绑定顺序很重要? [复制] 【发布时间】:2021-07-21 00:11:37 【问题描述】:

我正在使用 C++ 学习 OpenGL (3.3),我可以使用顶点缓冲区对象、顶点数组对象和索引缓冲区绘制简单的多边形,但我编写它们的方式仍然感觉有点像魔术,所以我想了解幕后发生的事情。

我对 OpenGL 使用的绑定系统有基本的了解。我也知道 VAO 本身包含绑定的索引缓冲区(指定为here),如果我没记错的话,绑定的顶点缓冲区也是如此。

按照这个逻辑,我首先绑定 VAO,然后创建我的 VBO(在幕后绑定在 VAO 的“内部”?),我可以在 VBO 上执行操作,它会全部工作。但是当我在完成设置后解绑我使用的缓冲区时,似乎我必须先解绑 VAO,然后是顶点和索引缓冲区,所以解绑的顺序与绑定相同,并且不是倒序。

这非常违反直觉。所以我的问题是,为什么解除绑定的顺序很重要?

(澄清一下,在调用glDrawElements之前,无论如何我都会重新绑定VAO,所以我认为我什至不需要解绑任何东西。这主要是为了学习目的)

以下是相关代码:

GLuint VAO, VBO, IBO;

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glBindVertexArray(0); //unbinding VAO here is fine
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//if I unbind VAO here instead, it won't render the shape anymore


while (!glfwWindowShouldClose(window)) 
    glfwPollEvents();

    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0);

    glfwSwapBuffers(window);

【问题讨论】:

看来我必须”你为什么认为你“必须”这样做? @NicolBolas 抱歉,如果从帖子中不清楚,我“必须” 因为多边形根本不会渲染。 我可以问“'否则'是什么意思?”,但如果你只是发布一些代码,它真的会快很多。 也许这会阐明你的三角形:***.com/questions/21652546/… 【参考方案1】:

我相信我可能已经弄明白了。 看看这个解除约束的顺序

glBindBuffer(GL_ARRAY_BUFFER, 0); //unbinding VBO
glBindVertexArray(0); //unbinding VAO

显然“破坏”了我的多边形,因为在我的 VAO 仍然绑定时解除绑定 VBO 意味着应该“包含”对其使用的缓冲区的引用的 VBO 现在不再绑定到顶点缓冲区。它不知道缓冲区。

首先解除绑定 VAO 允许我在不影响任何缓冲区的情况下解除绑定。这将是正确的顺序。

glBindVertexArray(0); //unbinding VAO
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbinding VBO

OpenGL 的绑定系统有点难以掌握,尤其是当不同的事物相互依赖时,但我认为我的解释是正确的。希望这对将来的其他学习者有所帮助。

【讨论】:

在 VAO 之前解除 GL_ARRAY_BUFFER 的绑定应该无关紧要。在 VAO 未绑定之前,GL_ELEMENT_ARRAY_BUFFER 可能不会未绑定。原因是调用glVertexAttribPointer时会存储VAO和数组缓冲区之间的连接,但对于元素数组缓冲区,除了绑定缓冲区之外,没有其他显式方式建立连接。

以上是关于为啥 OpenGL 缓冲区解除绑定顺序很重要? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

3.OpenGL渲染技巧

为啥从 FBO 解除绑定纹理会清除纹理?

为啥单击两次后我的事件侦听器与按钮解除绑定?

OpenGL:着色器存储缓冲区映射/绑定

为啥OpenGL不支持多索引缓冲?

将模板渲染缓冲区绑定到opengl中的帧缓冲区