Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL structure of VAO/VBO for model with moving parts?

Tags:

opengl

vbo

I came from this question:

opengl vbo advice

I use OpenGL 3.3 and will not to use deprecated features. Im using Assimp to import my blender models. But im a bit confused as to how much i should split them up in terms of VAO's and VBO's.

First off a little side question. I use glDrawElements, do that mean i cannot interleave my vertex attributes or can the VAO figure out using the glVertexAttribPointer and the glDrawElements offset to see where my vertex position is?

Main question i guess, boils down to how do i structure my VAO/VBO's for a model with multiple moving parts, and multiple meshes pr. part.

Each node in assimp can contain multiple meshes where each mesh has texture, vertices, normals, material etc. The nodes in assimp contains the transformations. Say i have a ship with a cannon turret on it. I want to be able to roatate the turret. Do this mean i will make the ship node a seperate VAO with VBO's for each mesh containing its attributes(or multiple VBO's etc.). I guess it goes like

draw(ship);    //call to draw ship VAO
pushMatrix(turretMatrix)  //updating uniform modelview matrix for the shader
draw(turret);  //call to draw turret VAO

I don't fully understand UBO(uniform buffer objects) yet, but it seems i can pass in multiple uniforms, will that help me contain a full model with moveable parts in a single VAO?

like image 396
CodeMonkey Avatar asked Jan 14 '12 13:01

CodeMonkey


People also ask

What is Vao and VBO in OpenGL?

Vertex Buffer Object (VBO) to store vertex data in GPU memory. Shader to define the program to execute on the GPU. Shader with Vertex Buffer Object (VBO) to invoke the Programmable Pipeline. Shader with Verrtex Array Object (VAO) an advanced concept of the Programmable Pipeline.

What is Vao in OpenGL?

A Vertex Array Object (VAO) is an OpenGL Object that stores all of the state needed to supply vertex data (with one minor exception noted below). It stores the format of the vertex data as well as the Buffer Objects (see below) providing the vertex data arrays.

Do you need a VAO in OpenGL?

In you use a core OpenGL context, you do need a VAO. If you don't, your code simply won't work. If you want to continue pretending you don't need a VAO, you can create a single VAO and have it bound for the entire duration of your program.

Does VAO bind VBO?

VBO's are only added to the state of the VAO when that VAO is bound. So any previously bound VBO's will not alter the state of the VAO that you are going to bind. The state of a bound VAO can be changed with the following calls: glEnableVertexAttribArray.


1 Answers

first, off VAO only "remembers" the last vertex attribute bindings (and VBO binding for an index buffer (the GL_ELEMENT_ARRAY_BUFFER_BINDING), if there is one). So it does not remember offsets in glDrawElements(), you need to call that later when using the VAO. It laso does not prevent you from using interleaved vertex arrays. Let me try to explain:

int vbo[3];
glGenBuffers(3, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, data0, size0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, data1, size1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data2, size2);
// create some buffers and fill them with data

int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// create a VAO

{
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), NULL); // this is VAO saved state
    glEnableVertexAttribArray(0); // this is VAO saved state
    // sets up one vertex attrib array from vbo[0] (say positions)

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); // not saved in VAO
    glVertexAttribPointer(1, 3, GL_FLOAT, false, 5 * sizeof(float), NULL); // this is VAO saved state
    glVertexAttribPointer(2, 2, GL_FLOAT, false, 5 * sizeof(float), (const void*)(2 * sizeof(float))); // this is VAO saved state
    glEnableVertexAttribArray(1); // this is VAO saved state
    glEnableVertexAttribArray(2); // this is VAO saved state
    // sets up two more VAAs from vbo[1] (say normals interleaved with texcoords)

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]); // this is VAO saved state
    // uses the third buffer as the source for indices
}
// set up state that VAO "remembers"

glBindVertexArray(0); // bind different vaos, etc ...

Later ...

glBindVertexArray(vao); // bind our VAO (so we have VAAs 0, 1 and 2 as well as index buffer)
glDrawElements(GL_TRIANGLE_STRIP, 57, GL_UNSIGNED_INT, NULL);
glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_INT, (const void*)(57 * sizeof(unsigned int)));
// draws two parts of the mesh as triangle strips

So you see ... you can draw interleaved vertex arrays using glDrawElements using a single VAO and one or more VBOs.

To answer the second part of your question, you either can have different VAOs and VBOs for different parts of the mesh (so drawing separate parts is easy), or you can fuse all into one VAO VBO pair (so you need not call glBind*() often) and use multiple glDraw*() calls to draw individual parts of the mesh (as seen in the code above - imagine the first glDrawElements() draws the ship and the second draws the turret, you just update some matrix uniform between the calls).

Because shaders can contain multiple modelview matrices in uniforms, you can also encode mesh id as another vertex attribute, and let the vertex shader choose which matrix to use to transform the vertex, based on this attribute. This idea can also be extended to using multiple matrices per a single vertex, with some weights assigned for each matrix. This is commonly used when animating organic objects such as player character (look up "skinning").

As uniform buffer objects go, the only advantage is that you can pack a lot of data into them and that they can be easily shared between shaders (just bind the UBO to any shader that is able to use it). There is no real advantage in using them for you, except if you would be to have objects with 1OOOs of matrices.

Also, i wrote the source codes above from memory. Let me know if there are some errors / problems ...

like image 118
the swine Avatar answered Sep 28 '22 01:09

the swine