Repeated GL Pointer Call Inquiry

Hey everyone, I’m currently working on something for OpenGL ES 2, and I have a question regarding the glEnableVertexAttribArray() and glVertexAttribPointer() calls.

I more or less understand what they do. However, I’m curious as to if it’s necessary to call them every single time you send data to the GPU. Basically I’m calling them once each for both the XYZ coordinates and the UV coordinates, then sending my data from a FloatBuffer with glBufferSubData(). I’m then calling glDrawElements() as I’m drawing via indices.

I’m wondering, though, if I can avoid making these four calls every single time I draw. Any advice regarding whether or not this is possible would be greatly appreciated.

If it was an option, I would just use VAOs, but I’d prefer not to use any of the extensions as I want to ensure device compatibility.

Thank you in advance!

Edit: Completely forgot to mention that I’m swapping between two VBOs and that they’re dynamic. My index buffer is, of course, static.

You can keep it on as your are doing draw calls, assuming you keep the same ones on for every draw call, you should turn them off after you are done doing draw calls, though you don’t necessarily have to.

Thank you, The Lion King, for the quick response!

By “keeping the same ones on for every draw call,” do you mean if my buffer is static, or is that in regard to something else? One thing I completely failed to mention is that I’m swapping between two dynamic vertex buffers, and that I’m consistently filling them with new data.

That’s not a problem, and I’ll give you an example of what I meant. Sometimes I draw objects and pass in color values to the shader so I disable the texture cord attribute and turn on the color one. This is the only time you have to worry about it. If you don’t have a similar situation don’t worry about it

Upload your vertex data to a VBO and glVertexAttribPointer() no longer any data, it simply tells OpenGL where to find it. Finally you can set up your vertex attributes once in a VAO and you only have to bind the VAO before rendering.

Thanks for the responses thus far! I figured something out with regard to my current setup that might narrow down my inquiry. Previously I had tried calling those two methods only once–setting and forgetting them, in other words. But, I noticed it ended up making everything look choppy. The speed was the same, but things weren’t quite smooth. So, I tried removing the VBO swapping I have going on, and it removed the choppiness. Basically, it was drawing from one VBO and ignoring the other, so it would only draw every other frame. In other words, it seems as though I’m required to call these two methods for each VBO I switch to. I’m assuming this is due to the fact that we have to inform OpenGL where to find data for that particular buffer, or something like that. Apologies for my lack of insight; I’m still not sure entirely how these two methods function on a lower level.

I guess what I’m wondering, then, is if there’s any way to specify this data for both of the VBOs and have OpenGL remember it, if that’s at all possible. While I’ve read the documentation, I’m not entirely sure what these two calls are doing under the hood. Also, theagentd, I would use a VAO but I’m using ES 2 and I don’t want to use extensions.

Also, it might help if I post the general flow of my drawing method, so here it is.


// Bind the active texture and VBO.
glBindTexture();
glBindBuffer();
// Call methods for XYZ coordinate data.
glEnableVertexAttribArray();
glVertexAttribPointer();
// Call methods for UV texture coordinate data.
glEnableVertexAttribArray();
glVertexAttribPointer();
// Send vertex data to the GPU.
glBufferSubData();
// Bind the IBO.
glBindBuffer();
// Draw the quads.
glDrawElements();

Thank you again for your help!

First some information on shader attributes. Let’s say you have a shader with two vertex attributes: [icode]in vec3 position[/icode] bound to location 0 and [icode]in vec2 texCoords[/icode] bound to location 1. You bind this shader. Then you bind your VBO, enable vertex attribute location 0 and call glVertexAttribPointer() for location 0 with correct values to read some position data from your VBO.

What does this do? If you answered “tells OpenGL where it should read data for the shader attribute ‘position’ from and also how OpenGL should interpret the data in that VBO”, you’d be wrong. Although that is the result, that is not what these calls do. These calls have no connection with the currently bound shader. When you call glEnableVertexAttribArray(0), OpenGL does not enabled the position attribute; it simply says that “attribute 0 should be read from an array”. What “attribute 0” refers to has not been decided yet, and may be changed if a different shader is bound. Hence, it’s perfectly okay to completely change the order of the above commands and get the exact same result as above:

Bind VBO --> enable vertex attribute 0 --> glVertexAttribPointer(0, …) —> bind shader.

The actual connection isn’t done until you actually render something. When you call glDrawArrays(…) or glDrawElements(), OpenGL will look at the vertex attributes of the current shader and do the following (some kind of pseudo code:

int location = locationOfAttribute(attributeName); //= 0 for "position"
if(glEnableVertexAttribArray(location) has been enabled){
    read data from the VBO that was bound when glVertexAttribPointer(location, ...) was called and interpret it as specified by glVertexAttribPointer(location, ...).
}else{
    use value of glVertexAttrib*(location, ...);
}

The fact that the attribute information about which attributes are enabled and what their values are is global state in OpenGL means that if you ever want to read attributes in more than one way in your entire program, you’ll need to set up your vertex attributes each time you want to read them in a different way or from a different VBO from your last render call.

VAOs are meant to solve this. Called Vertex ARRAY Objects, these objects do not store any data actual data (the vertex data still lies in VBOs), but it does store vertex attribute state, so vertex attribute state is no longer global; it is tied to the currently bound VAO. Therefore, you can do the following once:

int vao = glGenVertexArrays();
glBindVertexArray(vao);

glBindBuffer(GL_ARRAY_BUFFER, myVbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ...);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIbo);

glBindVertexArray(0); //Unbind the VAO.

At this point, glEnableVertexAttribArray(0) and glVertexAttribPointer(0, …) are “stored” in the VAO, including which buffer was bound when glVertexAttribPointer() was called (myVbo). Also, the VAO will store the call to glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIbo) for reading vertices. It will however NOT store the call to glBindBuffer(GL_ARRAY_BUFFER, myVbo). Which buffer is currently bound is stored when glVertexAttribPointer() is called. When we later want to render stuff, we can simply do the following:


//Update VBO
glBindBuffer(GL_ARRAY_BUFFER, myVbo);
glBufferSubData(...);


glUseProgram(myShader);
glBindTexture(...);
glBindVertexArray(myVao);

glDrawElements(...);

VAOs are meant to do exactly what you’re trying to do (to avoid having to set up vertex attributes each frame), and it cannot be done without VAOs.

More information: https://www.opengl.org/wiki/Vertex_Specification#Vertex_Array_Object