PDA

View Full Version : Vertex arrays and buffers in OpenGL 3/4



JoshKlint
09-18-2010, 12:12 AM
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.

Jacek Nowak
09-18-2010, 05:13 AM
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.

JoshKlint
09-18-2010, 03:30 PM
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);

JoshKlint
09-18-2010, 03:36 PM
Hmmm, this seems to work just fine:

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

marshats
09-18-2010, 07:29 PM
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);

arekkusu
09-18-2010, 08:53 PM
I have VBOs working, but I don't understand how to do client-side vertex arrays now.
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.

JoshKlint
09-18-2010, 08:56 PM
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?

Alfonse Reinheart
09-18-2010, 09:25 PM
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.

JoshKlint
09-18-2010, 09:48 PM
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?

marshats
09-18-2010, 10:39 PM
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 (http://www.flashbang.se/archives/131) 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*Ver texArrayCount,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.

Alfonse Reinheart
09-18-2010, 11:31 PM
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.

JoshKlint
09-19-2010, 09:16 AM
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.

marshats
09-19-2010, 09:50 AM
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.