Best vertex batching tecnique

#1

In my scene I have a huge numbers of objects.
I would like to group them in an optimal way in order to call less drawCalls as possible.

Grouping for me means put the vertices and other vertex properties of different objects in the same big VBO.
Of course this group of geometry has the same vertex attributes.

I was thinking to group them if they share the same shader program.
Lets make an example.

Suppose I have two objects with their own geometry, they use the same shader program but they differ in the material properties.
For material I mean the parameters that my shader can use as input such as shiness, color ecc.

The first object uses material1, the second one uses material2 and a different model matrix as well.
If I put them in the same VBO I can link once my shader program and call once a drawCall and I think this will be the best that I can obtain in order to reduce drawCalls.

Now my problems are (with the solutions that I was planning to implement):

  1. In my vertex shader, as usual, I have as uniform matrix the model, the view and the projection. Each of my two objects have a different model matrix but since they are in the same VBO I can set once the uniform for the model matrix before the drawCall.
  • Solution 1: use a uniform array in which I will put the different model matrices, then my objects will have as vertex attribute a personal ID that I will use to find the correct model matrix in the array. But this requires me to pass all the model matrices in a big uniform array.
  • Solution 2: apply on cpu the model matrix transformation to the vertices (I have already tried this solution for animation… Of course on cpu is really slow)
  1. In my fragment shader I have a uniform struct for the material which defines the shiness and so on. Again, each of my two objects have different material properties.
  • Solution: use also here a uniform array for the materials and access it using the ID.

This solution is inspired from the discussion here in the forum.

I would like to understand if this solution is a valid alternative in order to reduce drawCalls and have bigger VBO (with more vertices and other properties).
Any suggestions/ideas are really appreciated!

Thanks! :smiley:

#2

Well, you can’t change uniforms in the middle of a draw call, so if you want to merge draw calls you either need to convert the uniforms to attributes or (more realistically) store them in an array. With later OpenGL versions (GLSL 4.60 or ARB_shader_draw_parameters), you can use glMultiDrawElements (or some variant of it) and use gl_DrawID to index the array. Otherwise, the index needs to be an attribute.

If you have many objects and/or many uniforms, you may not be able to fit the array into the default uniform block. In which case use UBOs, SSBOs or buffer textures.

You don’t have to take batching to extremes. If you’re drawing thousands of objects, you don’t want a draw call per object. But nor do you have to render the entire scene in a single draw call. Multiple draw calls may be preferable to writing excessively complex shaders which handle every case.

#3

Thanks for the answer!
Yes I will use UBOs and glMultiDrawElements but unfortunatelly I have to use OpenGl version 3.3.

EDIT: I figured out that the solution I was looking for is related to glMultiDrawArraysIndirect, for the future here the link to its description