I'm interested to know how others would do / have done this.
Part 1. Constraints.
My current renderer is being built to support OpenGL ES 2.0 primarily and so aims for performant mobile as well as desktop. Separate render paths for mobile and desktop are avoided for simplicity's sake, so I'm discussing a single, unified ES 2.0 render path here, minimally targeting devices that support
I have different categories of renderables. Terrain chunks, for example, are fully opaque and with the depth buffer turned on, can be rendered in any order. So far, so good. Foliage OTOH consists of semi-transparent objects suited to alpha testing /
discard given a desktop GPU.
Part 2. Approach.
As a result, I must fall back to alpha blending and the painter's algorithm for transparent objects. So it seems there are two sort-categories of renderables, to be rendered separately and in this order:
- solid objects: no explicit sorting (or front-to-back for optimised z-reject), depth buffer write on
- transparent objects: back-to-front sort, depth buffer write off
(could there be more of these?)
Given this, I now wish to sort my display lists as efficiently as possible by minimising GL API calls. To this end, it seems best to:
- order the display list primarily by sort-category (as 1 & 2 above),
- (within same sort-category) order secondarily by similar material and thus shader program,
- (within same material-bucket) order tertiarily by similar mesh / vertex data.
And then of course render everything.
This way if we have same sort-category, same material, and same mesh on each of two objects,
glDrawInstanced() becomes a viable option to combine those two objects into a single draw call, and even if not, we've (hopefully) minimised the number of context changes that need occur.
Does the proposed render order 1-2-3 sound right? If not, explain differently, and justify.