Vertex arrays and buffers in OpenGL 3/4

I’m pretty confused about setting vertex/element arrays and buffers in OpenGL 3/4. My understanding of them comes from OpenGL 2.

  1. Are two pathways still supported (arrays and buffers)? Typically I would use buffers by default, and use vertex arrays for constantly changing data, like particle data.

  2. Can you point me to an explanation of the setup of vertex arrays and buffers in OpenGL 3/4, which explains how they are different from OpenGL 2?

Thanks.

http://www.opengl.org/sdk/docs/man3/

refer to this page for core context (I think that’s what you mean by OpenGL 3/4).

From what I see, vertex arrays aren’t removed, but predefined attributes are. So rather than use glVertexPointer,glTexCoordPointer,glNormalPointer,glColorPointer you will use glVertexAttribPointer/glEnableVertexAttribArray combo, with indices set explicitly in shader (GL_arb_explicit_attrib_location), retrieved from shader (glGetAttribLocation) or set up explicitly in code (glBindAttribLocation).

As for arrays vs buffers, I’d suggest benchmarking, maybe VBO with DYNAMIC_DRAW or STREAM_DRAW usage type will be as fast as arrays or maybe faster.

I have VBOs working, but I don’t understand how to do client-side vertex arrays now. Here’s what I am doing:

glEnableVertexAttribArray(target);
glBindVertexArray(vertexarray);
glVertexAttribPointer((GLuint)target,3,GL_FLOAT,GL_FALSE,0,data->buf);
glBindVertexArray(0);

Hmmm, this seems to work just fine:

            glEnableVertexAttribArray(target);
            glVertexAttribPointer((GLuint)target,3,GL_FLOAT,GL_FALSE,0,data->buf);

glEnableVertexAttribArray(target);
glBindVertexArray(vertexarray);
glVertexAttribPointer((GLuint)target,3,GL_FLOAT,GL_FALSE,0,data->buf);
glBindVertexArray(0);

The Vertex Array Object bound by glBindVertexArray(vertexarray) is subsequently set/affected by the following “Vertex Array Object State Associated Methods”


glVertexAttribPointer
glEnableVertexAttribArray
glVertexAttribDivisor
glBindBuffer

In your code above you called glEnableVertexAttribArray before binding the vertex array object – hence glEnableVertexAttribArray did not affect the VAO you expected. This explains why you observed things to work when you moved glEnableVertexAttribArray to just before glVertexAttribPointer. You could put it anywhere after glBindVertexArray(vertexarray); but before glBindVertexArray(0);

Client arrays aren’t supported in GL3/4 Core Profile:
“An INVALID_OPERATION error is generated (if…)
any of the *Pointer commands specifying the location and organization of vertex array data are called while zero is bound to the ARRAY_BUFFER buffer object binding point (see section 2.9.6), and the pointer argument is not NULL.”

They are deprecated:
“Client vertex and index arrays - all vertex array attribute and element array index pointers must refer to buffer objects.”

In Compatibility Profile, they still work.

I really do not understand how this new vertex array object works, and the documentation does not help. Where can I find an explanation in simple English?

This is what I am using to prepare the element buffer:

I don’t see how that worked in GL 2.0. You didn’t bind the buffer to GL_ELEMENT_ARRAY_BUFFER before calling glDrawElements. Or if you did, you didn’t consider that code interesting enough to post.

I didn’t both including it. If nothing has changed for element arrays and buffers since GL 2, there is no problem with my existing code.

Vertex array objects aren’t actually required are they?

One possible reference worth reading is the new OpenGL Superbible , 5th edition by Richard S. Wright, Jr. et all. This book covers only openGL 3+.

The link is not an explaination but gives a motivation for VAOs. The idea is that you create buffer objects that store state information related to attributes (like mesh coorids, normals, colors, etc any thing you need) and the vertex array object stores all the state information about all those buffers so you don’t have to do a bunch of enable/vertexattribs for each attribute you need.

A typical use example is something like


 //Create geometry vertex array using Model definition
  GLuint vao;
  glGenVertexArrays(1,&vao);
  glBindVertexArray(vao);

  //in vec3 vert;
  GLuint bon_vert; // buffer object name
  glGenBuffers(1,&bon_vert);
  glBindBuffer(GL_ARRAY_BUFFER,bon_vert);
  glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*3*VertexArrayCount,vertices,GL_STATIC_DRAW);
  const GLint loc_vert(glGetAttribLocation(program,"vert"));
  glVertexAttribPointer(loc_vert,3,GL_FLOAT,GL_TRUE,0,NULL);
  glEnableVertexAttribArray(loc_vert);

  //in vec3 normal; --- ie repeat for all other attributes your shader uses
  GLuint bon_normal; // buffer object name
  glGenBuffers(1,&bon_normal);
... 
/******************************************************* 
 now the vertices, normals, and any other attributes are
 stored in the VAO, no need to glVertexAttribPointer/glEnableVertexAttribArray anymore.
Also, glBufferData puts the data in GL memory and your local
memory is no longer needed -- that is it is 
no-longer client side-- notice how the last argument of glVertexAttribPointer
is no longer your array but a offset, in this case null or 
zero offset because of the particular way 
glBufferData was used.
********************************************************/

 //Create a  second geometry vertex array using Model
 // ie simply repeat the above code with a new geometry, normals, etc 
...

  //Render loop
  SDL_Event event;
  do {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLE_STRIP,0,VertexArrayCount);

    glBindVertexArray(vao2);
    glDrawArrays(GL_TRIANGLE_STRIP,0,VertexArrayCount2);

    SDL_GL_SwapWindow(window);

    SDL_PollEvent(&event); //non-blocking
  } while (event.type!=SDL_MOUSEBUTTONDOWN);


Notice how simple the Render loop is ie no excessive calls to enable and set vertex attributes on and off due to the pre-defined VAOs.

Vertex array objects aren’t actually required are they?

In core OpenGL, you need to create at least one VAO. But if you don’t want to use VAOs for their intended purpose, you are not required to. Just create one and bind it after initializing your GL context, then forget about it. Everything should then work as you expect.

This seems like an extra layer of complexity with no purpose. My rendering calls already use my own abstracted classes, so I will do without. Thanks.

This seems like an extra layer of complexity with no purpose.

Interesting conclusion. I respectfully disagree with your idea that this VAO complicates things with no purpose – I see it as the opposite. They came in as a great helper when I started using Transform feedback when things became more complicated switching between ping-pong buffers during an iteration algorithm (think physics collision simulation). Without VAO my head was spinning trying to manually enable/disable/swap the correct buffers. There were plainly too many things for me to keep track of the explicit way without VAOs.

Later on, you may want to revisit the idea of VAOs but for now I can understand you having a class that works a certain way and you just want to update it to continue on with other more interesting problems.