As we all know, batching things is good for performance. However, there are several ways to sort/group things. And I'm wondering if I'm going the right way. I have 3 examples in my engine, and would like to know if the sorting can be done more efficient.
* For the info, this is mainly an indoor situation, and I'm using OpenGL, though I assume the principles are the same regardless the rendering platform.
Several rooms are visible, each with props like furniture, boxes, lamps, decorations, and so on. Typically, such an object has 500 to 2.000 triangles, and 1 "material". A material is:
- a vertex / fragment shader
- Sometimes a geometry shader (rare)
- Shader parameters (textures, color-vectors, factors, ...)
Let's say I have 100 objects to render. Currently, I sort on material. So if there are 50 boxes and 50 barrels, the rendering loop could look as follow:
1- apply material "box" (shaders + set textures/parameters) 2- for each box in boxes glPushMatrix; glMultMatrix( box.matrix ); box.renderVBO; // Render the raw mesh via a VBO glPopMatrix; 3- apply material "barrel" 4- for each barrel .... see step 2So, we only had to switch materials/textures twice instead of 100 times. However, I could also sort on mesh VBO. Now for each object, the VBO mesh gets set (glBindBufferARB), rendered, unset.
* DirectX has "instancing"... can that be compared to this?
In that case I only have to activate the VBO twice, then repeat the render call. But obviously, this causes more material switches. In practice all the objects with the same VBO have the same material as well, but it will still cause more material switches. 4 different box-models may still share the same material, and thus get grouped together in case I sort per material.
Anyway, how would you sort / batch it?
Example2: Static geometry (walls, floors, pillars, ...)
Since I'm using a portal-rendering approach, the world gets split up in rooms. Then currently each room gets split up in material-groups. For example:
1- All polygons using material "wood floor"
2- All polygons using material "brick walls"
3- All polygons using material "metal support bars"
4- All polygons using material "concrete ceiling"
Usually the polycount for each "polygon chunk" is very small, since walls/floors are usually simple shapes. A 6-face box room would have 2 tris for group1 (wood floor), 8 tris for the walls, and so on. In practice, the polycount is a bit higher in my case; the average room uses ~2.000 polygons in total. And 1 to 10 rooms are visible at the same time, usually.
Before rendering, all the chunks from all visible rooms are grouped together. So if there are 10 rooms visible, all using the same brick-walls, all those small chunks get grouped together. The render-loop would look like this:
1- material "wood floor" apply (set shaders, textures, parameters) 2- for each floorChunk_using_Wood chunk.render; // glDrawArray (vertices, normals, tangents, weights, texcoords)This minimizes the amount of material switches. But in case multiple rooms are visible, I'm rendering quite a lot small geometry pieces, using glDrawArray (no VBO's).
Another method I used is rendering per room & a VBO. First a VBO that contains all the geometry (vertices, normals, tangents, weights, texcoords) for the entire room will be activated. Then for each material, I apply the material and render a piece of that VBO via indices:
for each visibleRoom room.activateVBO; for each chunkSortedOnMaterial in roomChunks chunk.material.apply chunk.renderVBO_viaIndices room.deactivateVBO;Geometry wise, this seems a smarter way. Although I'm not sure the relative small polycounts (~2k per room) makes a real difference. The big disadvantage however, is that when there are 10 rooms visible, we need to repeat this 10 times too. Even if all rooms are using the same materials.
* Got to mention that each surface (floor, wall, ...) can use quite a lot texture data each (up to 16 MB texture data all together).
In both cases, I'm still rendering small parts of the room. Combining rooms and thus their geometru would fix that, but does not coop with the portal-rendering approach of course.
Example3: Transparent objects (trees, plants, windows, bottles, ...)
This one is nasty. I could sort in the similar ways, but obviously that causes depth issues. If I sort purely on depth, batching is near to impossible. Will I sort on material and/or mesh, the depth-order gets screwed up.
Now fortunately, I have little transparent objects. But I wonder how a game like Crysis renders its jungle. I mean, that uses a lot of transparent surfaces right?