4

VAO 是顶点数组对象,VBO 是顶点缓冲区对象。创建和绑定/解除绑定 VAO 和 VBO 的调用具有如下一般格式:

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

        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, 
                            sizeof(GLfloat)* 9,
                            vertices,
                            GL_STATIC_DRAW);
            glVertexAttribPointer(0,
                    3, GL_FLOAT, GL_FALSE,
                    0, 0);
            glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);    

我在互联网上关注了一些教程,他们说 VBO 绑定到 VAO,但是在上面的代码中,我不明白 VBO 和 VAO 之间的“连接”或“绑定”是如何建立的? 我的意思是我们如何知道哪个 VBO 绑定到哪个 VAO 以及如果一个 VBO 绑定到多个 VAO 怎么办?

所以,基本问题是:VBO 绑定到 VAO 是什么意思,我们如何知道哪个 VBO 绑定到哪个 VAO 以及这个绑定是如何建立的?

4

1 回答 1

13

VBO 如何连接到 VAO

它在glVertexAttribPointer被调用时附加。

Vertex Array Objects状态向量中声明的每个属性都可以引用不同的Vertex Buffer Object。该引用在glVertexAttribPointer被调用时存储。然后将当前绑定到目标的缓冲区ARRAY_BUFFER与属性相关联,并将对象的名称(值)存储在 VAO 的状态向量中。ARRAY_BUFFER绑定是一个全局状态 。

这与索引缓冲区( ELEMENT_ARRAY_BUFFER) 的行为不同。索引缓冲区绑定在顶点数组对象中声明。当缓冲区绑定到 targetELEMENT_ARRAY_BUFFER时,此缓冲区与当前绑定的顶点数组对象相关联。


这意味着当您调用时glBindBuffer(GL_ARRAY_BUFFER, VBO);,会设置一个全局状态来存储VBO. glVertexAttribPointer从全局状态检索VBO并将其关联到VAO. 当glBindBuffer(GL_ARRAY_BUFFER, ...)再次调用时,之前的绑定就丢失了,当然它不会改变 VAO 的任何状态。

glBindVertexArray(VAO);              # bind VAO (global state)

glBindBuffer(GL_ARRAY_BUFFER, VBO1); # bind VBO1 (global state)
glVertexAttribPointer(0, ...);       # associate VBO1 to attribute 0 in VAO

glBindBuffer(GL_ARRAY_BUFFER, VBO2); # bind VBO2 (change global state, VBO1 binding is lost)
glVertexAttribPointer(1, ...);       # associate VBO2 to attribute 1 in VAO
于 2020-01-24T07:40:43.570 回答