How do I update the contents of a VertexArrayBuffer - opengl

I have created a VAO with 2 vertex array buffers. The 1st buffer contains the coordinates of the verticies while the 2nd one contains 4 data values (type GLbyte) for each vertex.
/*
** Create a VAO and bind it
*/
glCreateVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
/*
** Create a buffer and initilise it
*/
glCreateBuffers(1, &vertex_buffer);
glNamedBufferStorage(vertex_buffer, sizeof(verticies), verticies, 0);
/*
** Bind the buffer to the VAO
*/
glVertexArrayVertexBuffer(vertex_array_object, 0, vertex_buffer, 0, sizeof(float)*3);
/*
** Specify the data format,
*/
glVertexArrayAttribFormat(vertex_array_object,0, 3, GL_FLOAT, GL_FALSE, 0);
/*
** Specify the vertex buffer binding for this attribute
*/
glVertexArrayAttribBinding(vertex_array_object,0,0);
/*
** Enable the attribute
*/
glEnableVertexArrayAttrib(vertex_array_object,0);
/*
** Now repeat for another buffer to hold per vertex data
**
** Create and initilise it
*/
glCreateBuffers(1, &nvd_buffer);
glNamedBufferStorage(nvd_buffer, sizeof(vectors), vectors, 0);
/*
** Bind the buffer to the VAO
*/
glVertexArrayVertexBuffer(vertex_array_object, 1, nvd_buffer, 0, sizeof(GLbyte)*4);
/*
** Specify the data format,
*/
glVertexArrayAttribFormat(vertex_array_object, 1, 4, GL_BYTE, GL_FALSE, 0);
/*
** Specify the vertex buffer binding for this attribute
*/
glVertexArrayAttribBinding(vertex_array_object,1,1);
/*
** Enable the attribute
*/
glEnableVertexArrayAttrib(vertex_array_object,1);
This all works and my Vertex Shader can access the data in the 2nd buffer and pass it to the Geometry Shader where it's used to create additional points.
Later on I want to update the data in the 2nd buffer and I can't see how I can do that. I think I should be using
glNamedBufferSubData(....)
but I can't work out how to get the buffer that I need to feed into this function from the VAO. I know I could store the original value assigned to "nvd_buffer" but is there a way to get this information directly from the VAO as I know the binding index I use to bind the buffer to the VAO
glVertexArrayVertexBuffer(vertex_array_object, 1, nvd_buffer, 0, sizeof(GLbyte)*4);

You should not want to ask a VAO which buffer objects are stored within it. There are a number of reasons for this.
When specifying the DSA functions for VAO queries, there was a... hiccup. The enumerators weren't actually specified to work for the DSA query functions correctly. That issue has since been resolved in the specification, but that doesn't mean any such fixes filtered out to implementations that implemented the broken spec language. So, there is some question as to whether any such queries will succeed.
You told OpenGL which buffer to use. Therefore, you already know the answer. There's no reason to ask a question to which you already know the answer. If you have chosen to forget the answer, you can just as easily choose not to forget it. So this is a problem you already have the tools to solve, and you shouldn't make OpenGL solve it for you.
You should not treat buffer objects as though they are owned by a VAO that uses them. They are their own resource and should be managed distinctly from any VAO(s) that use them. Indeed, most VAO usage (particularly with separate attribute formats) will attach different buffers to the VAO throughout the render loop. So in those cases, the linkage between a buffer and a VAO that uses it is entirely ephemeral.
Lifetime issues. If you delete the buffer object name when the VAO is not bound to the context, the buffer object will continue to exist until it is no longer attached to any VAOs. If you query the buffer object from the VAO, then you will effectively bring the name back to "life", but still in a way that will disappear when it is no longer used by such buffers. That can cause errors that are very hard to detect. So if you don't query names from OpenGL, this kind of error will be impossible.
All that having been said, the function you're looking for is glGetVertexArrayIndexediv. Since the documentation has not, as of this writing, been updated in accord with the bug fix I mentioned in item 1, it won't tell you the right enumerator to use. So the query looks like this:
GLuint buffer;
glGetVertexArrayIndexediv(vao, binding_index, GL_VERTEX_BINDING_BUFFER, reinterpret_cast<GLint*>(&buffer));
Where binding_index is the index you passed to glVertexArrayVertexBuffer.
However, that won't actually make your uploading code work. Oh yes, it will give you a valid buffer object name, but you can't upload to it. Why?
Because you told OpenGL that you would not. Right here:
glNamedBufferStorage(vertex_buffer, sizeof(verticies), verticies, 0);
The 0 there is the usage flag you gave to the immutable storage buffer you just created. With mutable buffers, the usage hint is only a hint; it doesn't constrain your ability to use it.
That is not the case with immutable storage buffers. If you do not specify that you will manipulate the data storage from the CPU in a certain way, then you cannot manipulate it in that way. So if you want to use glNamedBufferSubData on an immutable storage buffer, you must tell OpenGL you intend to do that by providing the appropriate flag. Specifically, GL_DYNAMIC_STORAGE_BIT.

Related

Understanding VAO, VBO and program

I have been learning OpenGL by myself, and some concepts in OpenGL confuses me.
I understand that VBO is the buffer resides on the server side for undescribed data, VAO is the description of the VBO, and Program is the shader rendering pipeline used to display meshes to the screen.
what keeps confusing me is the relationship between all three of them, as I can see, after VBO is created and filled, VAO is the generated for program attributes specification. does that mean each time when we bind a VAO we have to use certain program ahead? please correct me if this is not correct. and some brief introduction about interactive between these OpenGL concepts would be great.
thanks
does that mean each time when we bind a VAO we have to use certain program ahead
The VAO describes (among other things) the format of vertex data. As a part of that format, it describes which data goes to which vertex attributes. It does this by assigning attributes "locations".
Your vertex shader has a number of user-defined input variables. These inputs are each assigned a "location".
When you render, the vertex format specifies which VS inputs are filled in, based on the locations that match. Therefore, you don't have to restrict your usage of a VAO to a specific VS. But, you must use a VAO with a compatible program. One which has inputs that match the format's locations.
If your VAO specifies that attribute locations 0, 1, and 4 will be filled with floating point data, then any VS's you use with that VAO must be compatible with that. It technically doesn't have to actually use locations 0, 1, or 4, but if it does, it must use floating-point input values. Any unused locations provided by the format will effectively be ignored (though they will almost certainly still be read from the buffer).
If the VAO puts floating-point data in attributes 0, 1, and 4, but the VS expects unsigned integer data in attribute 1, then you have a problem.

Process of setting up a VAO in OpenGL

Can I get a more overall/general description of this?
I've been trying to research these things all week, but I only come into super technical explanations or examples.
Could somebody explain the overall process or goal of these VAO's? Maybe outline a bit of a "step-by-step" flowchart for setting up a VAO in OpenGL?
I've never been someone who learns by examples... so all the things I've found online have been really unhelpful so far.
Your Vertex Buffer Objects (VBOs) contain the vertex data. You set up attribute pointers which specify how that data should be accessed and interpreted in order to draw a vertex - how many components are there to each vertex, how are they stored (GL_FLOAT for example) etc.
The Vertex Array Object (VAO) saves all these attributes. Their purpose is to allow you to set up these attributes once and then restore them with one state change whenever you need to use them.
The advantage of this is you can easily set up multiple states and restore them - if I want to draw a cube and a triangle these are two different states - I create a VAO for each and the VAO saves the state for each of them. When I want to draw the cube, I restore the state for the cube only.
Setup
Setup has four steps:
Create the VAO
Bind the VAO
Set up the state
Unbind the VAO
Creating a VAO is very simple:
GLuint vao_name;
glGenVertexArrays(1, &vao_name);
This will generate one vertex array, and store it's name in vao_name.
Once your VAO is created you need to bind it:
glBindVertexArray(vao_name);
Now, any changes you make to the attribute pointers or bindings to the element array buffer will be saved. This is a call to any of the following:
glVertexAttribPointer(...)
glEnableVertexAttribArray(...)
glDisableVertexAttribArray(...)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
Whenever you make one of these calls, the corresponding state is saved in the currently bound VAO. And when you later bind the VAO again, the state is restored.
Once you have set up the state you can unbind the VAO. Do this by binding VAO 0:
glBindVertexArrays(0);
You could also bind a different VAO and set up a different state for that. When this happens it is safe to make changes to the attribute pointers without disrupting your previous state.
Drawing
When you want to draw something all you have to do is restore the VAO:
glBindVertexArray(cube_vao)
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(triangle_vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0); //Unbind the VAO
Edit:
These are some answers that helped me when I was trying to understand VAOs:
glVertexAttribPointer overwrite, glVertexAttribPointer clarification, When should glVertexAttribPointer be called?
Also, the OpenGL specification explains it well once you've got your head around the basics: https://www.opengl.org/registry/
The VAO holds all information about how to read the attributes from the VBOs.
This includes for each attribute, which VBO it is in; the offset, the stride, how it is encoded (int, float, normalized or not), how many values per attribute. In other words the parameters of glVertexAttribPointer (and the bound GL_ARRAY_BUFFER at the time of the call.
It also holds the element array buffer that holds the indexes.
For what VAO's are, see #ratchet-freak's answer.
As for the goal of VAO's, it's a matter of improving performance by allowing one single state change to setup all vertex attributes bindings, which not only means fewer function calls but also more opportunity for the OpenGL implementation to optimize for this state as a whole.
For VAO, an understanding of VBOs and Shader is a pre-requisite. VAOs provide a way to “pre-define” vertex data and its attributes.
One way to understand is to draw with VBOs and then draw the same with VAOs. You will notice that it is similar to drawing with VBOs, except that it is first "saved" in a VAO for later use. Subsequently, the VAO is made active to actually draw the saved state.
See VBO, Shader, VAO for a fairly good example.

Drawing multiple models using multiple openGL VBO's

rather than post lots of code, I will phrase this question intuitively. I hope you understand what I am getting at.
I am making a game and in the code I have a model class that loads a model and sets up the VBO for it.
In the loading function, it generates a new VBO ID and loads the vertex data from a file into that buffer by binding it etc. (This works fine)
At the beginning of the program I make one model object and load a .obj file.
In the render function, I simply call the DrawArrays() function (with the neccessary extra stuff) and as I said, everything works fine as the model appears on the screen with no problems.
The problem however, is when I make two model objects at the beginning of the program and load a different .obj file into each one.
The issue is that when I play, only the second model is drawn on screen.
The problem is because I don't properly understand how VBO's work.
This is how I "think" VBO's work.
You can generate as many VBO ID's as you want.
You can bind each ID to make it the active buffer.
You can load vertex data into that buffer.
You now effectively have many different ID's each referring to a "set of vertex data".
By calling the DrawArray function it draws every buffer you have generated (effectively displaying all your models on screen)
Now I know this is wrong because in my limited understanding I can't see how I could turn models on/off. But no matter how many tutorials I look at I can't answer this question because they all focus on displaying that ONE FIRST VBO, which incidentally I can do.
So... if that made sense, could anyone enlighten me?
You're doing it mostly right, but the drawing command does not draw every buffer you have generated. If you want to draw 2 objects with data in different buffers, you'll have to issue 2 drawing commands.
Let me explain, based on how I do it:
You create buffers using glGenBuffers. Before you can use a buffer, you have to "bind" it, that is, make it active using glBindBuffer. When a buffer is active, you can do stuff with it (populate with data for example). Note that there are different bind targets, so you can, for example, have one active array buffer (for vertex data) and one active element array buffer (for index data).
When you want to draw stuff, you have to specify what exactly you want to draw (I'll assume now that you're using your own shader) Usually you specify at least your vertex data and index data. To do this, you first bind your buffer with your vertex data (as an array buffer), then call glVertexAttribPointer with you attribute id. This tells OpenGL that the bound buffer is now the source for the current attribute. Then, you bind your index buffer as the element array buffer and call glDrawElements (not sure how glDrawArrays would work here).
You cannot use multiple VBOs at once for the same attribute - the call to bind another buffer just overwrites the previous call and makes the second buffer active, which, I assume, is why only your second object gets drawn.
You can also use VAOs to simplify the drawing - basically you assign an id to binding commands, then you can execute them with one line (think display lists).
So, my loading (of one object) looks like this:
Create buffers (let's say buffer 1 is for vertex data, buffer 2 for index data).
Bind buffer 1 as an array buffer.
Fill buffer with vertex data.
Repeat 2 and 3 for buffer 2 as element array buffer and index data, respectively.
And my drawing (again, of one object):
Bind buffer 1 as an array buffer.
Use glVertexAttribPointer to specify that this buffer goes to a specific attribute.
Bind buffer 2 as an element array buffer.
Call DrawElements
For the second object, you have to repeat everything.
Follow these steps to render your models, assuming model1 vertices are stored in vertexBuffer and model2 vertices in vertexBuffer2:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
//swap buffers depending on your windowing toolkit
Make sure to not perform glClear in the middle of the two model renders.
All the best!
what you want to do is set the vertexArrayAttribute back to the first object data before each call to drawArrays
the draw arrays function uses the bindings stored in the VAO to find the data needed to render everything
so to render 2 models you create a second VAO bind it and call glVertexAttribPointer as needed. for drawing you bind the VAO and call drawArrays for each model

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();

is VertexAttribPointer needed after each BindBuffer?

I noticed that unless I re-call VertexAttribPointer, there's not input to shaders after a BindBuffer. Is that necessary? The shaders may not change in writing but only the buffers used.
tibur already answered to the actual question, but I thought I'd add some context.
glBindBuffer(GL_ARRAY_BUFFER, ...) by itself does not do anything. Think of it as an extra argument to glVertexAttribPointer.
Remember, you can bind multiple buffers to different attributes (say attrib 0 uses vbo 1, while attrib 1 and 2 use vbo 2). What API order would you see for that setup ?
With the actual API, it's something like:
glBindBuffer(GL_ARRAY_BUFFER, 1);
glVertexAttribPointer(0, ...)
glBindBuffer(GL_ARRAY_BUFFER, 2);
glVertexAttribPointer(1, ...)
glVertexAttribPointer(2, ...)
glDraw*(...)
Why would the specification work that way ? Well, it's backwards compatibility rearing its head. When VBOs were introduced, glVertexPointer et al. did not have any parameter to pass which buffer object to use. Either it was many new entrypoints for each semantic (VertexPointer/NormalPointer/TexCoordPointer...), or it was an extra entrypoint by itself, which just was acting as an extra parameter to the *Pointer calls. They chose the latter (as a side note, this is also why you have to pass an offset inside the buffer as a pointer).
According to OpenGL OpenGL specifications, page 51 (Buffer Object State), the state corresponding to the array pointers stores the buffer ID. That means that if you want to change the buffer object to draw with, you need to recall glVertexAttribPointer function.
glBindBuffer(1);
glVertexPointer(...);
glDrawArrays(...); /// Drawing will use buffer 1
glBindBuffer(2);
glDrawArrays(...); /// Drawing will still use buffer 1
glVertexPointer(...);
glDrawArrays(...); /// Drawing will now use buffer 2