I see that I can bind a vertex buffer using glBindBuffer(GL_ARRAY_BUFFER, vbo);. This works, and I can also bind an element array using glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);. When using these everything draws as desired.
In reading the OpenGL 4.4 specification in section 10.3.1 I find mention of glBindVertexBuffer. It looks like this permits binding multiple vertex buffers and then having them all rendered at once. Is this correct? Also, how does it differ from using glBindBuffer? Can you use an element array buffer when binding vertex buffers with this?
Actually, the point of glBindVertexBuffer (...) is entirely different.
The idea when it was introduced in GL_ARB_vertex_attrib_binding was to separate the fixed mapping that has always existed between vertex buffer and pointer and replace it with a more flexible system that allows you to setup a format for a vertex attribute, a binding location for the vertex buffer/attribute to use and then simply swap out the buffer bound to that location.
You will not simply be replacing a call to glBindBuffer (...) with this new function, you have at least two other functions you need to call to setup a generic vertex attribute to be able to take advantage of glBindVertexBuffer (...):
glVertexAttribFormat (...) - This is effectively the same thing as glVertexAttribPointer (...) except it does not setup a pointer, it merely establishes how the buffer that will be paired with this attribute is to be interpreted.
glVertexAttribBinding (...) - This associates the generic attribute location with a new type of binding location (vertex buffer binding) so that you can use glBindVertexBuffer (...) to bind your VBO to a location this attribute will use.
glVertexBindingDivisor (...) - This is a replacement for glVertexAttribDivisor(). This replacement respects the binding association between the Vertex Attribute index and the Binding Slot index made by glVertexAttribBinding(...). This is worth pointing out because it's name is somewhat out of form with the other two functions listed above, while the older glVertexAttribDivisor() appears more in-form, but is the wrong function to use.
To put this into perspective, I have included some pseudo-code from the extension specification that shows how glVertexAttribPointer (...) works in relation to this new API addition.
The commands:
void glVertexAttribPointer (GLuint index, GLint size, GLenum type,
GLboolean normalized, GLsizei stride,
const GLvoid *pointer);
void glVertexAttribIPointer (GLuint index, GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer);
void glVertexAttribLPointer (GLuint index, GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer);
Control vertex attribute state, a vertex buffer binding, and the mapping between a vertex attribute and a vertex buffer binding.
They are equivalent to (assuming no errors are generated):
if (no buffer is bound to GL_ARRAY_BUFFER and pointer != NULL)
{
generate GL_INVALID_OPERATION;
}
glVertexAttrib*Format (index, size, type, {normalized, }, 0);
glVertexAttribBinding (index, index);
if (stride != 0) {
effectiveStride = stride;
} else {
compute effectiveStride based on size/type;
}
GL_VERTEX_ATTRIB_ARRAY_STRIDE[index] = stride;
// GL_VERTEX_BINDING_STRIDE will be set to effectiveStride
// by glBindVertexBuffer.
glBindVertexBuffer (index, <buffer bound to GL_ARRAY_BUFFER>,
(GLchar *)pointer - (GLchar *)NULL, effectiveStride);
It is a little difficult to wrap your head around at first, but what it boils down to is very similar to the separation of sampler state from Texture Objects when Sampler Objects were introduced in GL 3.3. You can continue using the old API, but this alternative solution gives you some more flexibility.
Regarding element array buffers, no. This new part of the API has nothing to do with that, because Vertex Array Objects actually manage the one-and-only element array buffer binding.
Not really. glBindVertexBuffers
is used for binding multiple vertex buffers. As for glBindVertexBuffer, it is used for binding a buffer to a vertex buffer. You may have to call it many times to bind multiple vertex buffers.
You can check their documentation here:
http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexBuffers.xml
Related
I'm now maintaining an lagacy code and found "strange" usage in OpenGL.
First, the OpenGL version is 3.2 compability profile.
Then, there is nothing refering to VAO in the code, however, in Dont need to have a VAO? what #Dietrich Epp said is below :
If you use a compatibility OpenGL context, you don't need a VAO. In a sense, there is a "default" VAO which is always bound.
And what confused me is how the data are fed to OpenGL . The pseudocode may explain clear:
// foo.cpp
void PrimitiveLoading()
{
// load vertex position data
glBindBuffer(GL_ARRAY_BUFFER, postionVBO);
glBufferData(GL_ARRAY_BUFFER, /* postion data */);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// load vertex position index data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, positionEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, /* postion index data */);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// load UV data
glBindBuffer(GL_ARRAY_BUFFER, uvVBO, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, /* UV data */);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/*
The postion data are loaded before ELEMENT, while the UV data are behind.
This means ELEMENT is associated with the postion but not the UV, right?
*/
}
void PrimitiveRendering()
{
// define the vertex postion format
glBindBuffer(GL_ARRAY_BUFFER, postionVBO);
glVertexAttribPointer(/*position attribute setting*/);
// define the uv format
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glVertexAttribPointer(/*UV attribute setting*/);
glBindBuffer(GL_ARRAY_BUFFER, 0); // GL_ARRAY_BUFFER bind to 0
// draw
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, positionEBO);
glDrawElements(GL_TRIANGLES, positionEBO, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
/*
before drawing, GL_ARRAY_BUFFER bind to 0(not bind to both postionVBO and uvVBO), but it works.
And the data are fed to respectively postionVert and uvVert in foo.vert below as expected. how and why ?
Moreover, it seems the ELEMENT affects not not only postionVAO but also uvVAO.
*/
}
// foo.vert
version 150
in vec3 postionVert;
in vec2 uvVert;
...// other code
the questions are written as comments. Could anyone explain how this usage works?
The postion data are loaded before ELEMENT, while the UV data are behind.
This means ELEMENT is associated with the postion but not the UV, right?
No. Index arrays are not "associated" with any attribute. When you do indexed rendering, the index used applies to all attributes. You cannot use different indices to fetch different attributes.
before drawing, GL_ARRAY_BUFFER bind to 0(not bind to both postionVBO and uvVBO), but it works.
Of course it works. What is bound to GL_ARRAY_BUFFER does not matter for rendering purposes. It only matters when you call glVertexAttrib*Pointer, which takes the buffer that is currently bound to that binding point and hooks the given attribute index to that buffer.
Think of GL_ARRAY_BUFFER as just being a weird way of passing an additional parameter to glVertexAttrib*Pointer. Since you didn't call that function, the extra parameter isn't passed to anyone.
When you're "not using a VAO" in compatibility contexts, you're still using a VAO. The VAO-modifying functions all work exactly the same as they do for core contexts. The only difference is that in compatibility, VAO object 0 is a real vertex array object, while in core contexts it is not a valid object. So in compatibility contexts, there's always some VAO that is currently bound.
I thought the VAO (Vertex Array Object) was supposed to store state like the vertex attributes. When I create a VBO I specify my vertex attributes:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)nullptr);
glEnableVertexAttribArray(0);
// And so on
If I bind another VBO I have to call glVertexAttribPointer and glEnableVertexAttribArray three times, that's for every time I switch my VBO. I only have one VAO, I never change it. Is there something wrong? I only use one vertex layout and I'm not understanding what the VAO does if it loses this information each time I switch. Is it only one VBO per VAO?
If you don't want to respecify glVertexAttribPointer before calling a glDraw* function then you need several VAOs not just one. I think you are confusing the what a VBO and a VAO are. A VBO is just an inert piece of memory that contains data. A VAO contains all the information that OpenGL requires to draw a mesh, that includes:
- a reference to the Buffer object containing your vertex data (commonly named VBO)
- a reference to the Buffer object containing your vertex indices (if you are using glDrawElements*)
- the index of the different vertex attributes you are going to use and their layout in the Buffer object containing your vertex data (specified with glEnableVertexAttribArray and glVertexAttribPointer)
So basically for each mesh you are going to draw you need to prepare a corresponding vao:
// at scene preparation time
glBindVertexArray(vaoA); // the following functions will only affect vaoA
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshA);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshA);
foreach attrib of meshA
glEnableVertexAttribArray(***);
glVertexAttribPointer(***)
glBindVertexArray(0)
glBindVertexArray(vaoB); // the following functions will only affect vaoB
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshB);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshB);
foreach attrib of meshB
glEnableVertexAttribArray(***);
glVertexAttribPointer(***)
glBindVertexArray(0)
//And now at render time:
void render()
{
glBindVertexArray(vaoA);
glDrawElements(***);
glBindVertexArray(vaoB);
glDrawElements(***);
}
for more info check: https://www.opengl.org/wiki/Vertex_Specification
I am currently learning GFLW and OpenGL in C++, and I have come across a very weird error that I really can't figure out why it is occurring. I have two Vertex Buffers, one contains the data for a triangle, and the other contains data for a cube. When I create the Vertex Buffer for the Triangle and draw it without creating the Vertex Buffer for the Cube, it works perfectly and draws to the window the expected triangle. However, if I create the second Vertex Buffer and draw only the triangle again it becomes distorted.
Output when only the triangle Vertex Buffer is created:
Output when both the triangle Vertex Buffer and Cube Vertex Buffer are created (cube vertex buffer is never used)
Vertex Buffer's constructor
VertexBuffer(const GLvoid *data, GLsizeiptr size, GLenum mode, GLsizei count, GLsizei stride, ShaderInterface *shader, GLvoid *positionOffset, GLvoid *normalOffset);
Creating the two vertex buffers:
VertexBuffer *vertexBuffer=new VertexBuffer(vertices,sizeof(vertices),
GL_TRIANGLES,
3,
sizeof(GL_FLOAT)*3,
shaderArray->at(0),
NULL,
NULL);
vertexBufferArray->push_back(vertexBuffer);
VertexBuffer *cubeVertexBuffer=new VertexBuffer(cubeVertices,
sizeof(cubeVertices),
GL_TRIANGLES,
36,sizeof(VertexDataPN),
shaderArray->at(1),
(GLvoid*)(offsetof(VertexDataPN,positionCoordinates)),
(GLvoid*)(offsetof(VertexDataPN,normalCoordinates)));
//vertexBufferArray->push_back(cubeVertexBuffer);
And the contents of the constructor for my Vertex Buffer class:
glGenBuffers(1,&vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);
glBufferData(GL_ARRAY_BUFFER,size,data,GL_STATIC_DRAW);
Also, I have already checked that the vertexBufferID's are different for both of them. The Cube Vertex Buffer is never used or referenced to after it gets created. If anyone knows why this is occurring please let me know.
OpenGL is state-based, which means that objects that change OpenGL's internal state during their initialization can affect its behaviour even if they aren't subsequently used.
You are calling glBindBuffer in your vertex buffer constructor, which means that unless you call glBindBuffer later, the most recently bound buffer (the cube) will remain bound to GL_ARRAY_BUFFER and will be used during rendering.
You need to change your drawing code to call glBindBuffer with the buffer that you intend to use (e.g. the triangle one), before any calls to glVertexAttribPointer.
I've got a problem with drawing an buffer object with no index. My other indexed vbos draw fine...
void drawArray(VertexArrayObject VAO)
{
GL11.glColor3d(1.0f, 0.2f, 0.2f);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VAO.southSkirtBufferID);
GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, VAO.southSkirtLength);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}
You are not using your "skirt buffer" for drawing. In drawArray you actually set the vertex pointer to point to the offset 0 in VAO.vertexBufferID (whatever that is, at that time. And you never set it to anything else.
The buffer reference is a part of the vertex attribute pointer, the currently bound GL_ARRAY_BUFFER at the time of the gl*Pointer() call will be used for that pointer. The GL_ARRAY_BUFFER binding at the time of the draw call is totally irrelevant, and just changing that binding does not affect the attribute pointers.
If you only render the skirts, it crashes because your attribute pointers aren't set up to anything useful at all.
I have a struct to store vertex data for 2 distinct models one is a cube the other a pyramid.
struct Model{
GLuint vboID;
GLfloat* vbo;
GLuint vaoID;
GLfloat* vao;
GLuint vertexStart;
GLuint vertexCount;
};
I create the vbos and generate their buffers like this:
Model cubeModel;
Model pyramidModel;
cubeModel.vbo = cubeVerts; //A GLfloat array I created earlier in code earlier.
cubeModel.vertexCount= sizeof(cubeVerts);//size of the GLfloat array in bytes
pyramidModel.vbo = pyVerts;
pyramidModel.vertexCount= sizeof(pyVerts);
glGenBuffers(1, &cubeModel.vboID); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, cubeModel.vboID); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, cubeModel.vertexCount, cubeModel.vbo, GL_STATIC_DRAW);
And then to draw I use:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, cubeModel.vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
Which works, and I successfully draw the cube, But i've been trying multiple ways to draw the pyramid as well.
What do I need to do to render both on screen at the same time?
EDIT: Here's what i've tried specifically, duplicating the glBufferData() call and passing in the pyramid data then making glDrawArays(GL_TRIANGLES,0,cubeModel.drawcount+pyramidModel.drawCount) figuring the vertex data would stack and glDrawArrays would go through all the geometry passed in one go.
I've also tried making 2 sets of instructions from glGenBuffers() to glDisableClientState() but instead using all of pyramid model's data. This was interesting because my glDrawArrays was:
glDrawArrays(GL_TRIANGLES, 0, cubeModel.drawCount);
glTranslatef(4.0f,0.0f,0.0f);
glDrawArrays(GL_TRIANGLES, 0, pyramidModel.drawCount);
and it ended up drawing a really messed up pyramid 2 times, leading me to believe that when I cal glBufferData() twice the second time Overwrites the data previously passed.
EDIT 2:After Reading Andon's comment I edited some of my code to clarify things, drawCount is now vertexCount, and m_vertexBuffer is now correctly referencing the handle I stored in cubeModel, cubeModel.vboID, instead of using an old class variable I was using to store the handle.
I do not want to muddy up the comments section, because there are a lot of things wrong with your code. But I also do not have time to go through all of them right now, so this is a sort of temporary answer.
glBufferData (...) does not technically overwrite previously passed data, it does something far worse. Every time you call glBufferData (...) it creates a new data store of the size you pass and (optionally) fills it with the data you supply (if you pass something non-NULL). Think of it more like calling free (...) and then malloc (...) or delete [] ... and new Type [...].
glBufferSubData (...) is the preferred technique for appending vertices to a vertex buffer. Unfortunately it does not resize the data store. Sometimes it is handy to over-allocate your VBO and defer supplying it data until later on (using glBufferSubData).
If you use one VBO to store both of your models, you need to know the starting vertex and the vertex count for each model as it relates to your VBO's data. Right now all you know is the number of vertices (and you have it named strangely drawCount instead of vertexCount). To most people, drawCount indicates the number of times you want to draw something, rather than the number of vertices or elements it contains.
The size field of a call to glBufferData (...) is supposed to be the size in bytes of your vertex data. Right now you're passing the number of vertices. More than likely you meant to use sizeof (YourVertexDataStructure) for the size of an individual vertex (sizeof (float [3]) in this case), and something like sizeof (cubeVerts) / sizeof (YourVertexDataStructure) to calculate the number of vertices actually stored in this array. Then the size you pass to glBufferData (...) would be: _size * count_