For this issue of the ever-continuing "Performance Art" series, I'll talk a little about flat-shaded or colored polygons and the use (or overuse) of bones in a model.
Always use a texture:
In the past, when the memory on graphics cards was very small, we tried to save texture space by flat-shading or assigning a single color to groups of polygons. This provided color information to parts of a model that didn't need the detail of a texture and saved memory in the process. However, with the advent of pixel shaders and graphics cards with a gig of memory on them, this is actually a performance killer now. The reason for this is simple, every unique color is a new constant switch. And every constant switch is a new draw call. So those 100 flat shaded objects in our models that we thought would save texture space are now actually causing 100 new draw calls. Sure, they're cheap draw calls, but they are draw calls none the less. So how do we fix this problem? Simple. Save a small space in the texture sheet to have 4x4 blocks of solid color. Anything that needs to reference that color, simply take all the UVs for those parts and shrink them way down to fit in the center of that 4x4 block (with room on the edges to compensate for mips). Voila, it's still a single draw call and you get the benefit of saving texture space since you're only using the equivalent of a 64x64 texture sheet for a full 256 colors. That can easily be fit in the gaps of a standard 1024x1024 texture sheet.
Bones Ain't Free (especially not ones in a big 'ol hierarchy)
Bones are a wonderful thing. They allow us to do animation on the vertex level without having to store transforms for each vertex in a mesh (anyone want to try storing matrix transforms for 1000 vertices? Okay, I know, you can do it in a texture, but that's out of scope for this discussion and still not free!) They also allow us to combine disparate animated parts in a model into a single draw call. However, there is a cost to having bones in a model. The hierarchy must be traversed recursively for each update for each frame. If you have a single node or possibly two in the hierarchy (like is the case for most of our autoskinning), then this is relatively cheap. Update parent node, update child node with parent's transforms, update child node with child's transforms, draw. 3 transforms and a draw. Well adding a single node to the chain drastically increases the complexity of the updates: Update parent node, update child1 node with parent's transforms, update child2 node with parent's transforms, update child1 with child1's transforms, update child2 with child1's transforms, update child2 with child2's transforms, draw. It's a geometric progression that goes from 3 updates for 2 bones to 6 for 3 to 12 for 4 to 24 for 5. And that's every frame. I've seen some third party add-ons that have literally hundreds of bones, many with hierarchies 3 to 6 bones deep (and sometimes more). That's great for saving draw calls, but not so great for performance overall. That would be the equivalent of making an aircraft that has every single Half-Life 2 character you might see onscreen at once as the wings. And that's only one instance of that aircraft. Imagine multi-player...
Hopefully this helps. Keep your hierarchies simple and make sure to always have a texture. We let out a lot of rope with this version of Flight Simulator. As you watch us swinging from it, please listen to what we've got to say, that way only one of us has to hang.
Thanks for the discussion of bones. I have been experimenting making trees with bones for a while now. So far the effect looks pretty cool. The trees only annimate with bones at LOD_90 so the frame rate seems fairly friendly - although I have not tested with many trees at once yet. We shall see and now I'll be sure to keep bones at a minimum.
the discussion of bones by Kevin on the DevCon was very helpful, so is your reiteration of it here. We DO want to have animated shapes in FSX bt don't want to kill the fun at the same time... tough work! ;-)
Really appreciating all the fascinating information you're providing here Adrian.. please keep it up. I've been particularly interested in your posts on the batching processes, and would be very keen to learn even more about it, especially on how not to break it ( which does seem a little easy to do).
Of course every designer has read the excellent blog posts by Adrian Woods on how to optimize your performance