0

Usually I try to separate mesh specific information (VBO/VAO) from instance specific information (transform, uniforms, etc).

In this way parts of the code which manipulate instance info do not need to know anything about VBOs/VAOs, and vice-versa.

However, recently I have started to use hardware instancing using glDrawInstanced and the fact that instance attributes are bound together in the VAO is making my separation of concerns harder.

The reason is that usually the VBO/VAO was constructed from my .OBJ loader (which has all the info necessary to build this) and then other parts of the code only worried about shader uniforms. Now, these parts of the code need to know about the structure of the VAO in order to attach the info about their instance attributes.

This becomes even more annoying when I have VBOs which may be reused for both normal and instanced rendering.

Is there a recommended way that would allow keeping a separation of concerns between setting mesh attributes and instance attributes?

I thought of having two VAOs, one for normal rendering and another for instanced rendering where I would add the extra instance attributes I need, but I found no way to duplicate or inspect the original VAO data so it seems that my components need to know the actual structure of the VBO/VAO and not just about the instance parameters.

glopes
  • 4,038
  • 3
  • 26
  • 29
  • Create another level of abstraction over your geometry, that will create and draw batches of data in a specified way (with or without instancing). – Ivan Aksamentov - Drop Apr 16 '16 at 22:17
  • Yea, this is precisely what I was hoping to avoid... I will do it ultimately if no other suggestions crop up. – glopes Apr 16 '16 at 22:20

1 Answers1

0

Found a way to do it!

I forgot that you can actually inspect the state of a VAO by using glGetVertexAttrib*. This allows my instance parameter manipulation modules to actually create a new VAO for instancing and reconstruct its basic structure from the original mesh VAO, and then add the additional attributes for the instancing parameters.

This way they can remain independent of the specific vertex structure of the mesh and need to worry only about the structure of the instancing data.

Inspection goes something like this:

std::vector<VertexAttrib> attribs;
for (int i = 0; ; i++)
{
  int enabled;
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
  if (enabled == 0) break;

  VertexAttrib attrib;
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib.size);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib.stride);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib.type);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib.normalized);
  attribs.push_back(attrib);
}

VertexAttrib is my own structure to store introspected vertex attribute states.

Once I have the list of introspected states, I just create and bind my new VAO and set its state to be the same of the original VAO. Then I proceed to add the extra attributes for hardware instancing. This also has the advantage that I can bind this new VAO to the original VBO and reuse exact same mesh data.

Then everything proceeds as per the normal instancing pipeline. If I need to draw the model without instancing, I can also just bind the original VAO.

glopes
  • 4,038
  • 3
  • 26
  • 29