Reputation: 1044
I'm trying to wrap my head around some of the openGL render options.
For now my sudo code goes in something like this:
void paint() {
...
for (auto &obj:objList) {
obj.draw(matrix)
}
}
void draw(matrix &m){
shaderProgram->bind();
meshVao->bind();
meshVertex->bind();
meshIndices->bind();
shaderProgram->setUniformValue("mvp_matrix", m * getObjTrans());
shaderProgram->setUniformValue("un_color", QVector4D(1, 1, 1, 1));
shaderProgram->enableAttributeArray("position");
shaderProgram->setAttributeBuffer("position", GL_FLOAT, 0, 3);
glDrawElements(GL_TRIANGLES, mMeshData->mIndices.size(), GL_UNSIGNED_INT, 0);
}
Now this just binds every object 1 by 1, sets its matrix, and draw it. Its fairly inneficient with lets say 5-20k+objects.
Now I was reading lately and from what I can say I could also load all objects data in to 1-2 VBO under 1 VAO and then draw them all in 1 call. So if I take all indices in to 1 vector and all vertex in to 1 vector, I can then bind just these 2 vbo objects and draw all objects in 1 call. The probem I try to understand is, how do I pass a matrix for each object in the vectors? In function above, I pass a matrix to each obj before drawing it, but if all my objects are in 1-2 vectors, how am I to pass matrix to them separately?
A rough last second idea would be to create a vector matrix. And pass all matrices in to that 1 vector and pass that in to the fragment/pixel shader. Then have an offset counter in there and every next object render, just do matrix[offset*16]
and this will give me matrix for that object. Once thats there all I need is matrix[offset*16]
until matrix[offset*16+16]
to get all 16 floats to create matrix and use to draw the object?
Is this the right direction?
Upvotes: 4
Views: 1508
Reputation: 45332
Have a look at Approaching Zero Driver Overhead (ADZO) techniques. In particular, have a look at ARB_multi_draw_indirect
(in core since OpenGL 4.3) and ARB_shader_draw_parameters
(in core since OpenGL 4.6). The latter will give you a gl_DrawID
input for your vertex shader which can be used to index into UBOs, SSBOs or TBOs holding per-object data like model matrices, texture array layer, materials or whatever.
For cases where gl_DrawID
is not available (GL 4.6 support isn't universal currently), there is a relatively clever workaround: http://www.g-truc.net/post-0518.html
. By using glglVertexAttribDivisor
of 1, a single attribute value is used for all data of one instance - and a non-instanced draw call is just defined to be equivalent to an instanced draw-call with an instance count of 1
- so you get the same value for all vertices in that particular draw call.That way, you only need a relatively small buffer with just one ID per object, you do not have to replicate it for every vertex of the object. And with multi draw indirect call, you can specify many of those with just a singe actual draw call.
Upvotes: 3