Reusing a buffer binding between VAO and old VBO - opengl

Assume I have a VAO which I assigned a VBO with id A via glVertexAttribPointer at index 0. Now I delete the VBO via glDeleteBuffers. A new VBO is created via glGenBuffers that coincidentally again receives id A. Now my question: If I want to use this new VBO in place of the old one with the VAO, with the same parameters, do I have to call glVertexAttribPointer again even if the ids of the VBOs are the same?

Related

Does it make sense to connect a texture to a VAO?

When I have different vertex attribute configurations bound to a VAO I can easily change the VAO and render different things. But those different things might need different textures too. Does it makes sense to bind textures to VAO too so that when you change the VAO the same texture index is populated with different data?
A VAO is essentially a table of all values passed into glVertexAttribPointer() as well as a reference to the VBO that was bound at the time when glEnableVertexAttribArray() was called. There is no way to connect a texture to a particular VBO, and you will have to do this yourself manually prior to rendering your VAO.

attaching a vertex buffer object to a vertex array object

I am trying to attach a vbo to a vao. However I only get it to work the "old" way:
bind vao
bind vbo
glVertexAttribPointer(...)
glEnableVertexArrayAttrib(...)
unbind vbo
unbind vao
Now I want it to implement the new bindless way, I tried it like this:
glVertexArrayAttribFormat(...);
glVertexArrayVertexBuffer(...);
glVertexArrayAttribBinding(...);
However then I only get a black screen.
Attaching the index buffer object to the vao works though:
glVertexArrayElementBuffer(...);
What am I missing?
Seems like I was missing
glEnableVertexArrayAttrib(...)
Thus, the correct replacement would be
glEnableVertexArrayAttrib(...);
glVertexArrayVertexBuffer(...);
glVertexArrayAttribFormat(...);
glVertexArrayAttribBinding(...);
And don't forget to set the stride in glVertexArrayVertexBuffer(...), it should not be 0!

When should glVertexAttribPointer be called?

It's not obvious from the documentation when glVertexAttribPointer should be called. It looks like it's part of VBO initialisation, but I notice example code calling it during rendering.
glVertexAttribPointer(vertexAttributeId, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<const GLvoid*>(offsetof(Vertex2D, m_x)));
Should glVertexAttribPointer be called during initialisation of a GL_ARRAY_BUFFER or should it be called during rendering (after a call to glBindBuffer)?
The function glVertexAttribPointer specifies the format and source buffer (ignoring the deprecated usage of client arrays) of a vertex attribute that is used when rendering something (i.e. the next glDraw... call).
Now there are two scenarios. You either use vertex array objects (VAOs) or you don't (though not using VAOs is deprecated and discouraged/prohibited in modern OpenGL). If you're not using VAOs, then you would usually call glVertexAttribPointer (and the corresponding glEnableVertexAttribArray) right before rendering to setup the state properly. If using VAOs though, you actually call it (and the enable function) inside the VAO creation code (which is usually part of some initialization or object creation), since its settings are stored inside the VAO and all you need to do when rendering is bind the VAO and call a draw function.
But no matter when you call glVertexAttribPointer, you should bind the corresponding buffer right before (no matter when that was actually created and filled), since the glVertexAttribPointer function sets the currently bound GL_ARRAY_BUFFER as source buffer for this attribute (and stores this setting, so afterwards you can freely bind another VBO).
So in modern OpenGL using VAOs (which is recommended), it's usually similar to this workflow:
//initialization
glGenVertexArrays
glBindVertexArray
glGenBuffers
glBindBuffer
glBufferData
glVertexAttribPointer
glEnableVertexAttribArray
glBindVertexArray(0)
glDeleteBuffers //you can already delete it after the VAO is unbound, since the
//VAO still references it, keeping it alive (see comments below).
...
//rendering
glBindVertexArray
glDrawWhatever
When not using VAOs it would be something like that:
//initialization
glGenBuffers
glBindBuffer
glBufferData
...
//rendering
glBindBuffer
glVertexAttribPointer
glEnableVertexAttribArray
glDrawWhatever
glVertexAttribPointer is something that does not really belong to the Buffer nor to the Program it is - let's say - the glue between them. (The functionality of this is splitten in Opengl 4.3 in different functions VertexAttrib*Format, VertexAttribBinding and BindVertexBuffer aviable through the ARB_vertex_attrib_binding )
But if you want to say that it is part of something i would say it is part of the VAO that stores the state of which Buffer objects are bound, which attribs are enabled and how the Buffer data has to be passed to the Program.
So it belongs to part where you setup your VAOs.
EDIT
Simple setup that illustrates the order:
creating/setup of Buffers and creating programs
create VAO define which attribs are enabled, which buffers should be bound when the VAO is used and how that data is passed to the program (glVertexAttribPointer)
The association of buffer, generic vertex attribute and shader attribute variable are quite subtle. glVertexAttribPointer establishes this association. See OpenGL-Terminology for a detailed explanation.
Also, the link OpenGL-VBO,shader,VAO shows a working example with the necessary sequence of API calls.
glVertexAttribPointer has to be called (in most cases) when the appropriate (i.e. the one you want to use) VBO is bound. Then last parameter to it is offset in said buffer.
The last parameter is defined particularly nice in the reference manual:
Specifies a offset of the first component of the first generic vertex
attribute in the array in the data store of the buffer currently bound
to the GL_ARRAY_BUFFER target. The initial value is 0.
Appropriate Vertex Pointer Bindings with VBO sources are stored inside VAO, and you should use that if possible.
Short example (excuse my pseudocode):
// Setup
CreateVAO(); BindVAO();
CreateVBO(); BindVBO();
VertexAttribPointer(/*id*/ 0, 3, GL_FLOAT, /*starting at offset*/ 0);
// We have specified Vertex attribute bound to location 0,
// with size of 3 floats, starting at offset 0 of VBO we've just created.
//Draw
BindVAO();
Draw();

OpenGL, VAOs and multiple buffers

I am writing a little graphics engine using OpenGL ( via OpenTK with C# ).
To define vertex attributes, I have a VertexDeclaration class with an array of VertexElement structures that are mapped to glEnableVertexAttribArray/glVertexAttribPointer calls.
Also, to support multiple vertex streams, I have a special structure holding a vertex buffer, vertex declaration, vertex offset and instance frequency (like the XNA's VertexBufferBinding structure).
Currently, whenever a drawing call is invoked, I iterate over all the set vertex streams and
bind their vertex buffers, apply vertex declarations, disable unused vertex attributes and draw the primitives.
I would like to use VAOs to cache the glEnableVertexAttribArray calls into them,
and whenever a vertex stream is applied, bind the VAO and change its array buffer binding.
Is that a correct usage of VAOs?
Is that a correct usage of VAOs?
No1.
glVertexAttribPointer uses the buffer object that was bound to GL_ARRAY_BUFFER at the moment the function was called. So you can't do this:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
This will not use bufferObject; it will use whatever was bound to GL_ARRAY_BUFFER when glVertexAttribPointer was originally called.
VAOs capture this state. So the VAO will, for each vertex attribute, store whatever buffer object was bound to GL_ARRAY_BUFFER when it was called. This allows you to do things like this:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
Attributes 0 and 1 will come from buffer1, and attribute 2 will come from buffer2. VAO now captures all of that state. To render, you just do this:
glBindVertexArray(VAO);
glDraw*();
In short, if you want to change where an attribute's storage comes from in OpenGL, you must also change it's format. Even if it's the same format, you must call glVertexAttribPointer again.
1: This discussion assumes you're not using the new ARB_vertex_attrib_binding. Or, as it is otherwise known, "Exactly how Direct3D does vertex attribute binding." If you happen to be using an implementation that offers this extension, you can effectively do what you're talking about, because the attribute format is not tied with the buffer object's storage. Also, the tortured logic of glVertexAttribPointer is gone.
In general, the way we solve this in the OpenGL world is to put as many things as possible in the same buffer object. Failing that, just use one VAO for each object.

Do I need to rebuild my VAO if I need to change a VBO?

I'm rendering my scene by constructing or modifying a buffer that I give to glBufferData. My understanding of Vertex Array Objects is that they allow me to skip the manual binding of all of the VBOs I am using. Is this still the case when I update my buffer all the time?
Can I bind my VAO, call glBufferData to update the vertices and indices (the only two VBOs I have at the moment), and then render?
Can I use memory mapping with the VBO's? Then I could bind VAO, modify buffer, then render?
What exactly does the VAO do? Is its function simply that of a shortcut which stores and automates the binding of vertex attributes to my VBO's? Does it take ownership of either the data or the bindings?
You would probably have to test this, but from my understanding VBOs are given IDs when generated and a VAO only references each vertex attrib along with the VBO ID it's using. You should be able to call glBufferData or glBufferSubData. I'm not sure if memory mapping just before the draw call would work, but you could certainly do things between binding the VAO and drawing. A VAO doesn't lock the VBOs or restrict access to them.
In general, a VAO just stores attributes and all their settings (bound VBO, stride, offset, etc.) and automatically binds the attributes when bound. Until you call glBindVertexArray(0);, all vertex attributes are tied to the bound VAO.