Hello,
I’m creating my own game engine and need to improve the performance of my render loop.
I am testing with a 16x16x16 grid of cubes with unique vertices and indices - so no instancing - totaling 4096 cubes.
Currently, all my vertices and indices are in the same buffer. (not sure if this is a good idea or not)
I bind the following before drawing.
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
Each mesh has it’s own draw command held in GL_DRAW_INDIRECT_BUFFER which is also bound before drawing.
I then loop through each mesh and draw using the appropriate command buffer index. (mesh->buffer_id)
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (const void*)(mesh->buffer_id* sizeof(DrawBufferCommand)), 1, 0);
Which totals 4096 draw calls.
I’d like to speed up this approach and the first thing I tried was store the meshes in order in the DRAW_INDIRECT_BUFFER so that I could pass in the count as 4096 and call DrawElementsIndirect() once rather than 4k times. Like this.
uint32_t start = 0;
uint32_t count = 4096;
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (const void*)(start * sizeof(DrawBufferCommand)), count, 0);
However it provided no speed improvement. the FPS were exactly the same which made me think that under the hood of that function it might be calling the draw comand to the GPU the same amount if times as specifed in “count”.
Anyway, I’m unsure on what the best approach to take here is.
Being that all my vertex and indice data is in one array, I could simply create one draw command with the relevant vertex, indice offsets and counts to treat all 4k cubes as one mesh. It’ll draw okay, however entity ID’s for transforms would then have to be a per vertex attribute - which might be okay but further down the track I see no way of culling unwanted meshes - apart from using a compute shader to edit the indice’s so that offscreen geometry is not in the indice list. Don’t know about performance but might be worth testing.
I am hoping someone smarter than I am can point me in the right direction!
- Am I using the draw command correctly?
- Have I got the right idea?
- How do modern game engines render large amounts of geometry?
- I know a compute shader can fill the DRAW_INDIRECT_ARRAY but can a shader dispatch the draw? I mean, can it basically call it’s own equivalent of DrawElementsIndirect()?
Any help here is appreciated. ![]()