When creating a 3D model for a video game, modelers usually take into account various hardware and software limitations of the target platforms that will be running the game. When models are too complex, they can slow down processes on the device and ruin the player’s experience with delays and artifacts. In this case, 3D artists need to optimize the resources to boost the performance.
In this article, we’re going to cover such techniques as batching and LOD to help you produce a well-tuned 3D model
Optimization is the process of reducing a 3D model’s file size to ensure a higher frame rate. An optimized game works at the same frame rate across a wide range of hardware – including low-end configurations – and provides a better gameplay experience.
Every model in a game consists of polygons that are converted into triangles during the rendering process. A higher number of polygons means that the assets are more realistic and detailed, but their rendering requires many more resources.
Inexperienced modelers often try to reduce the number of triangles in order to optimize the 3D model representation. Although the lower number of polygons per mesh can improve the performance, optimization is not always about squashing everything into 5,000 triangles.
Check statistics in the engine to find out the frame rate
You should always bear in mind that the most important factor here is the time spent rendering a frame. This critical background process can be evaluated by:
Frame Debugger (Unity) decomposes a frame and evaluates the number of required draw calls
The number of draw calls is a very comprehensive parameter that shows the complexity of the frame. The more draw calls rendering has to push, the more time it takes to deliver one frame.
You should always focus on the number of draw calls you can have per frame based on your hardware and software requirements. Check this target value before you start decomposing the rendering process into separate commands.
The average number of draw calls per frame is as follows:
For example, Battlefield and the third Witcher game push about 1,000-2,000 draw calls, while the same value for PUBG varies from a reasonable amount of 5,000 up to an enormous one of 50,000.
These figures may not be relevant now, as technical capabilities of modern devices change very quickly. However, you should always target a certain number of draw calls for your game because it can easily become a bottleneck.
You can handle optimization in different ways depending on a particular render pipeline in your project.
Render pipeline is a model that describes what steps a graphics system needs to perform to render a 3D scene to a 2D screen. For example, Unity provides three pre-built render pipelines with different capabilities and performance characteristics, and you can also create your own system.
All pipelines are unique, complex systems, and each of them embraces optimization in its own way. However, you can use RenderDoc, Nvidia Nsight, or Intel Graphic Performance Analysis to check out frame rendering in a random PC game.
Generally, you can reduce the rendering time by:
Batching means combining multiple objects into batches for simultaneous processing.
Look at the picture below: there are ten boxes and one tree in a frame. All boxes have the same shader, material, and number of polygons. One can assume that we will have eleven draw calls because there are eleven objects in the frame. In fact, this frame requires only three draw calls.
The system sees that we have ten identical boxes in the frame and puts them together into one mesh. When we play the game, the GPU commands our video memory to draw this mesh as ten separate boxes on the screen.
Depending on the situation, you can use either dynamic or static batching.
Dynamic batching works with dynamic objects. It is a built-in automatic process that analyses the geometry and groups small details such as small fragments separated from the wall.
Dynamic batching reduces the number of draw calls but requires more CPU resources as each frame is processed separately.
Most render pipelines in Unity provide dynamic batching for dynamic geometry, so you can use it if you need to draw a lot of small, similar objects. For example, thousands of fish in a frame in Abzu are actually particles, with their geometry additionally animated by a vertex animation shader.
Note that dynamic batching has very strict limits, and you can’t use it for heavy geometry with more than 900 vertices.
Static batching works with static objects and is usually performed manually. You need to specify that this object is static, so that it will never be changed or shifted.
Static batching doesn’t reduce the number of draw calls per frame. Instead, it reduces the number of render state changes between them as it transforms the static objects into world space—that’s why you can’t destroy a wall or move a chair in a vast amount of games.
💡 Batching is a very effective technique in terms of optimizing your game performance, but it has some drawbacks. For example, when you apply batching, you can’t use Occlusion Culling that allows you to skip drawing objects that are not visible to the camera, such as a box blocked by another larger box.
If you don’t want to use batching, you can always manually merge your geometry for a specific scene and render the entire location in a single mesh.
Follow us on Instagram and we will send you invite to the courseFollow Instagram