is VertexAttribPointer needed after each BindBuffer? - opengl

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

Related

How do I update the contents of a VertexArrayBuffer

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.

Is it necessary to bind all VBOs (and textures) each frame?

I'm following basic tutorial on OpenGL 3.0. What is not clear to me why/if I have to bind, enable and unbind/disable all vertex buffers and textures each frame.
To me it seems too much gl**** calls which I guess have some overhead. For example here you see each frame several blocks like:
// do this for each mesh in scene
// vertexes
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer( 0, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer );
glVertexAttribPointer( 1, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// UVs
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, uv_buffer );
glVertexAttribPointer( 2, 2, GL_FLOAT,GL_FALSE,0,(void*)0);
// ...
glDrawArrays(GL_TRIANGLES, 0, nVerts );
// ...
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
imagine you have not just one but 100 different meshes each with it's own VBOs for vertexes,normas,UVs. Should I really do this procedure each frame for each of them? Sure I can encapsulate that complexity into some function/objects, but I worry about overheads of this gl**** function calls.
Is it not possible some part of this machinery to move from per frame loop into scene setup ?
Also I read that VAO is a way how to pack corresponding VBOs for one object together. And that binding VAO automatically binds corresponding VBOs. So I was thinking that maybe one VAO for each mesh (not instance) is how it should be done - but according to this answer it does not seems so?
First things first: Your concerns about GL call overhead have been addressed with the introduction of Vertex Array Objects (see #Criss answer). However the real problem with your train of thought is, that you equate VBOs with geometry meshes, i.e. give each geometry its own VBO.
That's not how you should see and use VBOs. VBOs are chunks of memory and you can put the data of several objects into a single VBO; you don't have to draw the whole thing, you can limit draw calls to subsets of a VBO. And you can coalesce geometries with similar or even identical drawing setup and draw them all at once with a single draw call. Either by having the right vertex index list, or by use of instancing.
When it comes to the binding state of textures… well, yeah, that's a bit more annoying. You really have to do the whole binding dance when switching textures. That's why in general you sort geometry by texture/shader before drawing, so that the amount of texture switches is minimized.
The last 3 or 4 generations of GPUs (as of late 2016) do support bindless textures though, where you can access textures through a 64 bit handle (effectively the address of the relevant data structure in some address space) in the shader. However bindless textures did not yet make it into the core OpenGL standard and you have to use vendor extensions to make use of it.
Another interesting approach (popularized by Id Tech 4) is virtual textures. You can allocate sparsely populated texture objects that are huge in their addressable size, but only part of them actually populated with data. During program execution you determine which areas of the texture are required and swap in the required data on demand.
You should use vertex array object (generated by glGenVertexArrays). Thanks to it you don't have to perform those calls everytime. Vertex buffer object stores:
Calls to glEnableVertexAttribArray or glDisableVertexAttribArray.
Vertex attribute configurations via glVertexAttribPointer.
Vertex buffer objects associated with vertex attributes by calls to
glVertexAttribPointer.
Maybe this will be better tutorial.
So that you can generate vao object, then bind it, perform the calls and unbind. Now in drawing loop you just have to bind vao.
Example:
glUseProgram(shaderId);
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(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.

glVertexAttribPointer clarification

Just want to make sure I understand this correctly (I'd ask on SO Chat, but it's dead in there!):
We've got a Vertex Array, which we make "current" by binding it
then we've got a Buffer, which we bind to a Target
then we fill that Target via glBufferData
which essentially populates whatever was bound to that target, i.e. our Buffer
and then we call glVertexAttribPointer which describes how the data is laid out -- the data being whatever is bound to GL_ARRAY_BUFFER
and this descriptor is saved to our original Vertex Array
(1) Is my understanding correct?
The documentation is a little sparse about how everything correlates.
(2) Is there some kind of default Vertex Array? Because I forgot/omitted glGenVertexArrays and glBindVertexArray and my program worked fine without it.
Edit: I missed a step... glEnableVertexAttribArray.
(3) Is the Vertex Attrib tied to the Vertex Array at the time glVertexAttribPointer is called, and then we can enable/disable that attrib via glEnableVertexAttribArray at any time, regardless of which Vertex Array is currently bound?
Or (3b) Is the Vertex Attrib tied to the Vertex Array at the time glEnableVertexAttribArray is called, and thus we can add the same Vertex Attrib to multiple Vertex Arrays by calling glEnableVertexAttribArray at different times, when different Vertex Arrays are bound?
Some of the terminology is a bit off:
A Vertex Array is just an array (typically a float[]) that contains vertex data. It doesn't need to be bound to anything. Not to be confused with a Vertex Array Object or VAO, which I will go over later
A Buffer Object, commonly referred to as a Vertex Buffer Object when storing vertices, or VBO for short, is what you're calling just a Buffer.
Nothing gets saved back to the vertex array, glVertexAttribPointer works exactly like glVertexPointer or glTexCoordPointer work, just instead of named attributes, you get to provide a number that specifies your own attribute. You pass this value as index. All your glVertexAttribPointer calls get queued up for the next time you call glDrawArrays or glDrawElements. If you have a VAO bound, the VAO will store the settings for all your attributes.
The main issue here is that you're confusing vertex attributes with VAOs. Vertex attributes are just the new way of defining vertices, texcoords, normals, etc. for drawing. VAOs store state. I'm first going to explain how drawing works with vertex attributes, then explain how you can cut down the number of method calls with VAOs:
You must enable an attribute before you can use it in a shader. For example, if you want to send vertices over to a shader, you're most likely going to send it as the first attribute, 0. So before you render, you need to enable it with glEnableVertexAttribArray(0);.
Now that an attribute is enabled, you need to define the data it's going to use. In order to do so you need to bind your VBO - glBindBuffer(GL_ARRAY_BUFFER, myBuffer);.
And now we can define the attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);. In order of parameter: 0 is the attribute you're defining, 3 is the size of each vertex, GL_FLOAT is the type, GL_FALSE means to not normalize each vertex, the last 2 zeros mean that there's no stride or offset on the vertices.
Draw something with it - glDrawArrays(GL_TRIANGLES, 0, 6);
The next thing you draw may not use attribute 0 (realistically it will, but this is an example), so we can disable it - glDisableVertexAttribArray(0);
Wrap that in glUseProgram() calls and you have a rendering system that works with shaders properly. But let's say you have 5 different attributes, vertices, texcoords, normals, color, and lightmap coordinates. First of all, you would be making a single glVertexAttribPointer call for each of these attributes, and you'd have to enable all the attributes beforehand. Let's say you define the attributes 0-4 as I have them listed. You would enable all of them like so:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
And then you would have to bind different VBOs for each attribute (unless you store them all in one VBO and use offsets/stride), then you need to make 5 different glVertexAttribPointer calls, from glVertexAttribPointer(0,...); to glVertexAttribPointer(4,...); for vertices to lightmap coordinates respectively.
Hopefully that system alone makes sense. Now I'm going to move on to VAOs to explain how to use them to cut down on the number of method calls when doing this type of rendering. Note that using a VAO is not necessary.
A Vertex Array Object or VAO is used to store the state of all the glVertexAttribPointer calls and the VBOs that were targeted when each of the glVertexAttribPointer calls were made.
You generate one with a call to glGenVertexArrays. To store everything you need in a VAO, bind it with glBindVertexArray, then do a full draw call. All the draw bind calls get intercepted and stored by the VAO. You can unbind the VAO with glBindVertexArray(0);
Now when you want to draw the object, you don't need to re-call all the VBO binds or the glVertexAttribPointer calls, you just need to bind the VAO with glBindVertexArray then call glDrawArrays or glDrawElements and you'll be drawing the exact same thing as though you were making all those method calls. You probably want to unbind the VAO afterwards too.
Once you unbind the VAO, all the state returns to how it was before you bound the VAO. I'm not sure if any changes you make while the VAO is bound is kept, but that can easily be figured out with a test program. I guess you can think of glBindVertexArray(0); as binding to the "default" VAO...
Update: Someone brought to my attention the need for the actual draw call. As it turns out, you don't actually need to do a FULL draw call when setting up the VAO, just all the binding stuff. Don't know why I thought it was necessary earlier, but it's fixed now.
The terminology and sequence of APIs to be called is quite confusing indeed. What's even more confusing is how the various aspects - buffer, generic vertex attribute and shader attribute variable get associated. See OpenGL-Terminology for a pretty good explanation.
Further, the link OpenGL-VBO,shader,VAO shows a simple example with the necessary API calls. It's particularly good for those transitioning from immediate mode to the programmable pipeline.
Hope it helps.
Edit: As you can see from the comments below, people can make assumptions and jump to conclusions. The reality is that it's quite confusing for beginners.