Do OpenGL Vertex Array Objects store vertex buffer

2020-03-05 07:13发布

问题:

When created, do VAOs track just VBO indices (via glBindVertexBuffer), or also which VBO names are bound to those indices? If I specify a binding index of, say, 0 using glVertexAttribBinding during VAO creation, can I bind a different VBO to index 0 just prior to a draw call and have it use the contents of that VBO, or will it always use whatever VBO was bound to index 0 at the time the VAO was created?

I ask because a lot of examples I find precede calls to glVertexAttribFormat and glVertexAttribBinding with a call to glBindVertexBuffer, which should not be necessary if the VAO tracks only indices (since the binding index is given in glVertexAttribBinding).

回答1:

As you're probably aware, this is fairly new functionality introduced in OpenGL 4.3. The way I read the spec, the mapping between attributes and buffers now has a level of indirection:

  1. Each attribute has a property that specifies which binding index it uses.
  2. Buffers are bound to binding indices.

You can look at this as two tables, one defining a mapping from attribute index to binding index, the other one from binding index to buffer name. Both of these tables are part of the VAO state.

I believe these can be specified completely independently, and in any order. glVertexAttribBinding() establishes the first association, between attribute index and binding index. glBindVertexBuffer() establishes the association between binding index and buffer name.

This understanding is confirmed by the state table in the spec. Table 23.4 in the GL 4.4 spec, captioned "Vertex Array Object State", lists:

  • VERTEX_ATTRIB_BINDING, which can be queried with glGetVertexAttribiv(), is the value of the binding index of a given attribute index.
  • VERTEX_BINDING_BUFFER, which can be queried with glGetIntegeri_v(), is the value of the buffer name for a given binding index.

Based on this, addressing your specific questions:

When created, do VAOs track just VBO indices (via glBindVertexBuffer), or also which VBO names are bound to those indices?

They track both.

can I bind a different VBO to index 0 just prior to a draw call and have it use the contents of that VBO

Yes, if you bind a different VBO to binding index 0, all attributes with binding index 0 will use the content of that VBO.

a lot of examples I find precede calls to glVertexAttribFormat and glVertexAttribBinding with a call to glBindVertexBuffer, which should not be necessary if the VAO tracks only indices

The VAO tracks the state set by all these calls, so it does make sense to use all of them as part of setting up the VAO. Tracking the entire vertex setup state in a VAO is the main purpose of having VAOs in the first place. It allows you to set up the state once during initialization, and then you need only a single call to glBindVertexArray() before your draw calls to set up the entire state again.



回答2:

The answer is that they DO NOT store vertex names, only indices. If you bind a different VBO to the same index in a different VAO, you must re-bind the first VBO again before any glDraw call that uses the first VAO.

At least on my Macbook Pro with:

Renderer: NVidia GeForce GT 650M OpenGL Engine

Version: 4.1 NVIDIA-10.0.43 310.41.05f01