2
\$\begingroup\$

Recently I'm trying to implement a render queue sorting system, i.e., ordering my renderable objects in an array in such a way that the overhead of OpenGL state changes are minumum. After some googling, the most ideal one (to me) is to generate an integer key value for each renderable object, and the sorting is based on that value. Once done sorting, objects that have similar rendering states (same shader, texture, distance, etc.) will be close to each other, so we can just loop through the object array and submit the draw calls for rendering.

Here's a detailed explanation: Order your graphics draw calls around!

My problem is, how do I loop through the renderable object's array to submit their draw calls for actual rendering? Do I need to keep track of the current OpenGL states manually?

What have come to my mind is:

(for each renderable object)
{
    if(objects[i].getShader() != m_currentShader)
    {
        m_currentShader = objects[i].getShader();
        m_currentShader.bind();
    }

    if(objects[i].getTexture() != m_currentTexture)
    {
        m_currentTexture = objects[i].getTexture();
        m_currentTexture.bind();
    }

    // ... and so on

    object[i].getMesh().draw();
}

Seems not so performance-friendly to me, but I can't find any further explanation on how to submit the actual draw calls form the object's array either on the article I've provided or other sites I can find. Perhaps there's something I have missed?

\$\endgroup\$
4
\$\begingroup\$

Some ideas:

  • You could ignore the issue, and do what you're currently doing. Assuming those texture and shader comparisons are to OpenGL IDs (which are just integers), it's unlikely those checks are going to create a huge performance bottleneck. Comparison of integer values on modern CPUs is rather fast. Unless your profiler has told you this is currently a problem I would not worry that much about it.

  • You could group instead of just sort; that is, find a way to assemble an aggregate key out of all the possible state you might check for and sort by and put the renderable objects into buckets based on that key. If all you're sorting by is shaders and textures, for example, a 32-bit key will give you several thousands of texture and shader IDs to work with. Using a simple bit-packed integers as a key is easy, but does tend to be limiting as you scale up the complexity of your game (you really start to lose bits once you have multiple textures in play, and so on). This sounds similar to what your current sorting key is, but it also sounds like that key isn't giving you quite the information you need in terms of state capture.

  • Finally, you can process a list of render commands instead of renderable objects. This command list contains both "objects to render" as well as "GPU commands to issue." When you do your initial sort of your actual renderable objects, you insert state-change commands into this command buffer as you find boundaries in the sorting groups where states change. Then you simply process this command list in a linear fashion, applying each command directly without state checks, confident that your earlier sorting pass has introduced the appropriate state change commands at the appropriate time. This is the most general of the three solutions I've presented, but is obviously a lot more work to implement than the first one.

\$\endgroup\$
  • \$\begingroup\$ Ahh thank you very much, these ideas are just what I need! You're awesome! \$\endgroup\$ – D01phiN Aug 11 '15 at 4:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.