Modularity and Drawcall

In game development you are dependent of your framerate. For having a smooth and pleasant rendering to offer to the player, you need a very well optimized scene. The first thing to look carefully is your polycount, obviously the more triangle you need to draw, the more calculation you will performs. So a very well optimized scene on the geometry will be displayed very fast.
Today, game engines and the current graphic cards are optimized to draw theses triangles, so you now can draw more triangles than before. This is why characters like Lara Croft (Tomb Raider Underworld) or Nathan drake (Uncharted) are created with an average of 40 000 triangles. Of course, theses characters are the main characters, but even monsters can be very high. For example a monster in Tomb Raider Underworld is made with 30 000 triangles.


Source : Polycount wiki and Tomb Raider Underworld

What is important to optimize ? Triangles are very well handled now, but what is important ? Well, you need to take care of the drawcalls.

Drawcalls

What is a drawcall ? A drawcall (also named “batch”) is a block of data sent by the CPU to the GPU. This block of data contain some polygons for each texture needed on a mesh. If by example you have one model of a tree (a texture for the trunk and an other one for the leaves), then you will send 2 drawcalls. And if you use this tree 4 times in your scene, then you will make 8 drawcalls (4 models * 2 textures). The drawcalls are called each frame, only what will be displayed is called, which mean if you rotate the camera, the drawcalls will change.
My example is not totally true about the textures : it’s not the texture which will cost, but the shader. Especially in DirectX, each time you change the shader, you need to recreate the pipeline which is used to create and display the shader. Even a little change could become a big cost.

By example, the DirectX version on Xbox 360 is cheaper than the classic DirectX on pc for especially optimize the drawcalls.
On PS3, if you use the native rendering (not OpenGL), there is a way to optimize this a little better, the shader will not be recreated from zero, but only the differences between the last shader and the new will be created.

Modularity and texture atlas

For avoiding performance hits, a simple trick is to merge your multiple textures into one big texture (also called “texture atlas”). By this way you will save some memory access (only one texture will be called for multiple object) and you will use only one shader to render them. Of course if you need a specific look on a particular texture, it’s not a good idea to merge it inside a texture atlas since all the effects will affect the other textures.


Example of a texture atlas (Source : Gamasutra article)

So, in a complex scene, every simple mesh will cost something. The problem is not the drawcall itself, but the number of drawcalls in whole. Since it’s the CPU which send the data (simple or complex polygons, textures, etc.), the problem will become the amount of drawcall that the CPU will be able to send. That’s mean that you will be CPU limited if you ask too much. Performances depends on how fast the CPU is and how much data the CPU can processes. The CPU will be too busy to doing nothing if you send smalls data (like 2 triangles by example), you will lost time while you are submitting the drawcall. It will take more time to send the data than the size of the data itself.

Optimization

The best advices to reduce the drawcalls are simple :
– Use few textures and texture atlas and avoid multiple mesh.
– Of course, simple shader will be achieved more faster than complex shader.
– Avoid very small meshes, try to merge them with other.
– Also be careful, do not merge all your scene or you will not be able to hide mesh which are not visible. (In UDK by example, when a little part of a mesh is visible, all the mesh is drew.)

Links

There is some cool scripts for 3DS Max and Maya to automatically generate texture atlas, for 3DS Max by example you have this one : Texture atlas generator (3DSMax).
A good tutorial about making texture atlas and modular environment is the one made by 3D Motive : 3D Motive – Modular building workflow in UDK.
A very good article on Gamasutra about texture atlas : Gamasutra – Practical texture atlases