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

I came from this question:

opengl vbo advice

I am using OpenGL 3.3 and will not use legacy features. I use Assimp to import my blender models. But I'm a little confused as far as I have to separate them in terms of VAO and VBO.

First a little question. I use glDrawElements, this means that I can not alternate the attributes of the vertices, or can the VAO figure out using glVertexAttribPointer and the offset glDrawElements to see where my vertex position is?

The main question, I think, comes down to how I structure my VAO / VBO for a model with several moving parts and several grids, etc. part.

Each node in a daze may contain several grids, where each grid has a texture, vertices, normals, material, etc. The nodes in the affinity contain transformations. Say I have a cannon tower on my ship. I want to lure the tower. This means that I will make the node ship a separate VAO with VBO for each grid containing its attributes (or several VBOs, etc.). I think it looks 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 do not yet fully understand UBO (uniform buffer objects), but it seems that I can go in several forms, will this help me to contain a complete model with moving parts in one VAO?

+7
source share
2 answers

firstly, outside the VAO, it only “remembers” the last vertex attribute bindings (and the VBO binding for the index buffer ( GL_ELEMENT_ARRAY_BUFFER_BINDING ), if one exists). Therefore, it does not remember the offsets in glDrawElements() , you need to call later when using VAO. This laso does not stop you from using alternating vertex arrays. Let me 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 alternating vertex arrays using glDrawElements , using one VAO and one or more VBOs.

To answer the second part of your question, you can have different VAO and VBOs for different parts of the grid (so drawing separate parts is easy), or you can combine all into one VAO VBO pair (so you don't need to call glBind*() ) and use several glDraw*() calls to draw individual parts of the grid (as you can see from the code above - imagine that the first glDrawElements() draws a ship and the second draws a turret, you just update some matrix form between calls).

Since shaders can contain multiple modelview matrices in uniforms, you can also encode the grid identifier as another vertex attribute and let the vertex shader choose which matrix to use for transforming the vertex based on this attribute. This idea can also be expanded by using several matrices at one vertex with some weights assigned to each matrix. This is commonly used when animating organic objects such as a player’s character (see “skinning”).

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

In addition, I wrote the source code from memory. Let me know if there are any errors / problems ...

+13
source

@theswine

Not linking this during VAO initialization causes my program to crash, but linking it after VAO binding makes it work correctly. Are you sure this is not stored in VAO?

 glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO 

(By the way: sorry for raising an old topic, I just thought it might be useful to others, this post was sure! (Which reminds me, thanks!))

0
source

All Articles