Those graphics rendering optimization tips were used when I work as a graphics programmer. Some of them are works at very low level which refer to how to write a graphics render engine. If you are work on on engine, such as Unity , Unreal and so on. Those works already done. But if you know these low level logic, you will work more effectively.
Generic Graphics Optimization skills:
- Cull the back surface;
- Use view frustum culling; objects or triangles can not be seen and no need to render
- Less draw call number;
- Batch those meshes that with the same materials;
- Use simpler shaders, consider carefully lighting in vertex shader and pixel shader; vertex lighting is faster than pixel lighting.
- Smaller texture or switch on use mipmap feature, use hardware supported texture compression;
- Use multiple instance instead of draw one mesh several times;
- Use vertex buffer objects or vertex array;
- Separate the the dynamic part from the static part when design the vertex attributes data structure, use vertex index and make the array become continues;
- sort the render state before rendering, mainly by the texture; For a group objects that to be rendered, those use texture-A render first and texture-B and so on. This method will result in less render state switch.
- Less rendering pass (or texture stage) will be better;
- Less pixel overlap shading. For example, you could render the sky box after all solid objects already rendered; Most of the skybox pixel will be skip because of z-test.
- Smaller frame buffer or render target. Use a smaller frame buffer for transparent objects and post-processing if possible. Smaller frame buffer means less pixels need to handle.
- Disable Multiple-Sampling, Disable Anti-aliasing!
- Disable the Gamma correct;
- Disable the dynamic shadow; try with fixed texture shadow
- Use light maps instead of the dynamic lighting;
- Limit the maximum skin character bone number; Or pre-bake the skin animation into vertex animation.
Shader Optimization Tips
Good FPS is the balance between art and technology. A good designed level and game play should take account the potential performance issue. After the optimization work on the high level was done, we could deep into the lower level, and do some investigation of shader part.
- Don’t reinvent the wheel, use intrinsic functions; Some one would like to write his own ‘dot’ function, this is not allowed;
- Use the most appropriate data types in calculations (float, half, fixed);
- Get rid of typecasting when it’s not need. Such as convert float3 to float4, float to float4, fixed to half, half to float…
- Instead of integers rely on floats for math;
- When indexing into arrays of constants use integers instead of floats;
- Combine scalar constants into full vectors, pack array elements into full constant vectors;
- For conditional compilation use boolean constants declared as static;
- Whenever possible vectorize code by joining similar operations together;
- Do not use expensive functions, such as log, exp, pow, sin, cos;
- Well arrange the variable calculations among application objects, per vertex and per fragment. Per fragment is the most expensive, per vertex is less expensive, and per object is cheap;
- Get rid of clip as possible, some one will suggest use alpha blend to replace alpha test;
- Remove branch statements. Some powerful device will support branch well, like K1 device uber-shader;
- Reduce the bandwith that pass from vertex shader to fragment shader;
- Use constant variables when you could make sure what those value is:
- Be careful on the precision such as float, half, fixed. Use theme properly, and get rid of typecast whenever possible.
Optimization is a forever topic in game development, not only for graphics but also for physics, game logic, assets load, network connect and so on. Those developer and designers always try to maximize their ideas on machine load, and try to not waste any machine capabilities.
When I was coding for console games, the artists always want to push so much assets into game box, lots of triangles on characters, very big size character textures, so many bones to high precision animation. To handle those problems, we need to do some ultimate test on device graphics capabilities, then we get some data report:
- the maximize number of triangle display on one screen
- the maximize number of traingle for characters, how many characters or enemies can be display on one screen.
- how many VFX can be display on the screen at the same time, and frame rate still good
- screen post-process effect, which one will cause frame-rate drop obviously
- video memory usage, how to range textures memory for scene, character, VFX
- lighting and shadow, maximize number of light sources can be placed in senne.
- physical CPU cost
- and so on
Base on this report, we write some assets standards for artists. And we introduce those rules into the asset export plugins to check whether those assets are beyond the standards too much.
Later I switched to a Unity developer, and the optimization issue still there. We need to investigate the document to find out all kinds of optimization skill and make game run fast. As times go, the mobile device become more powerful, and the developer want more. Every body knows that the more powerful device deserve more luxury, cool and more realistic graphics render.