From how I understand the two techniques (Primitive Restart and Base Index) explained on https://www.opengl.org/wiki/Vertex_Rendering , they both do the very same thing. Simply spoken, they allow me to put many meshes into the same buffer and then render them as multiple meshes again. Is my understanding right?
If my understanding is indeed right, then my next question would be how well either of them works together with indirect rendering and multi-rendering.
Let's just use the following example: I have multiple meshes, which are put together to one entity. Multiple entities are put together to one scene. In a scene, entity attributes, like location, textures,... might change. What would be the most optimized way to render them performance vise? By using glMultiDrawElementsBaseVertex() (is there an indirect version?) or by setting glPrimitiveRestartIndex() and then using glMultiDrawElementsIndirect()?
If there is no indirect variant for the former, shouldn't the latter be the better choice?
Of course, there might be a better way of doing things. If so, I would really like to hear it :)
1 Answer
For your first question yes your understanding is right.
Secondly I would argue that doing Multidraw*Indirect
(without glPrimitiveRestartIndex()
) would be better for performace (most optimized). The main thing to remember is that each OpenGL call you are doing is calling the OpenGL driver. So the more calls you do the more driver overhead you incurr.
A great place to look at how you can incurr minimal driver overhead is this presentation (slides) and the code @ github.
I'll give a brief example of what you have to do but you can go into more detail of the implementation with the links I've supplied.
Basically you fill your buffers (GL_ARRAY_BUFFER
or GL_ELEMENT_ARRAY_BUFFER
) and calculate your offsets into each model.
Then populate a draw command in either the form of
typedef struct {
GLuint _count;
GLuint _instanceCount;
GLuint _first;
GLuint _baseInstance;
} DAICmd;
for GL_ARRAY_BUFFER
(link on how to render) and
typedef struct {
GLuint _count;
GLuint _instanceCount;
GLuint _first;
GLuint _baseVertex;
GLuint _baseInstance;
} DEICmd;
for GL_ELEMENT_ARRAY_BUFFER
(link on how to render).
Each commands go into a GL_DRAW_INDIRECT_BUFFER
and your extra attributes (matrix transforms, texture handles, etc...) go into a GL_SHADER_STORAGE_BUFFER
.
You can access each attributes by asking OpenGL to generate them (like when you do instance rendering) or you can create a buffer of IDs.
After all this has been done you can do one OpenGL call draw everything you've batched.