There is not too much on this documentation wise, but the
OgreRenderQueue.cpp code is fairly good and clear:
Code: Select all
uint64 hash;
if( !transparent )
{
//Opaque objects are first sorted by material, then by mesh, then by depth front to back.
hash =
OGRE_RQ_HASH( subId, RqBits::SubRqIdBits, RqBits::SubRqIdShift ) |
OGRE_RQ_HASH( transparent, RqBits::TransparencyBits, RqBits::TransparencyShift ) |
OGRE_RQ_HASH( macroblock, RqBits::MacroblockBits, RqBits::MacroblockShift ) |
OGRE_RQ_HASH( hlmsHash, RqBits::ShaderBits, RqBits::ShaderShift ) |
OGRE_RQ_HASH( meshHash, RqBits::MeshBits, RqBits::MeshShift ) |
OGRE_RQ_HASH( texturehash, RqBits::TextureBits, RqBits::TextureShift ) |
OGRE_RQ_HASH( quantizedDepth, RqBits::DepthBits, RqBits::DepthShift );
}
In an ideal world, for optimal performance, everything would use the same shader and the same buffers (mesh and textures), and this is what ogre tries to achieve by putting multiple meshes into a single vertex buffer and textures into a textures array. Obviously this practically never really happens, but changing the GPU pipeline state, eg pixel shaders, or texture buffers, can be expensive, and cause GPU stalls. So Ogre orders its draw calls to minimise this. As you seen the code comment above, the comment 'sorted by material mesh and then depth'. Old system used to just sort by depth to try and reduce pixel overdraw, but its now more efficient to try and reduce pipeline state changes and let GPU crunch numbers. Also, if overdraw is an issue you just use a pre-z buffer.
The code is actually a bit more descriptive, and orders by
- macroblock (material specific values)
- HlmsHash (the shader, vertex, pixel, etc)
- meshHash (the vertex buffer)
- textureHash (the texture buffer state)
- quantizedDepth (depth order)
I am pretty sure the above is correct, but may need dark_sylinc stamp of approval!