Graphics Performance:Draw Call Batching

 

To draw an object to the Screen, the engine will issue a draw call to the graphics API (such as OpenGL or Direct3D). Draw calls are expensive, and each DrawCall does a lot of work together with the graphics API, resulting in CPU The performance overhead is mainly caused by state changes between DrawCalls (such as switching between different materials), which lead to expensive validation and transformation processes in the graphics driver.

 

Unity uses a few tricks to solve this problem:

  1) Static Batching , which combines static objects (such as non-moving ones) into one large Meshes for faster rendering.

   2) Dynamic Batching , for small enough Meshes, do some vertex transformations on the CPU, group similar meshes together, and draw them together.

The built-in Batching has several advantages over manually merging objects together, the most notable being that the merged objects can still be culled individually, but it also has some drawbacks, static batching will cause some memory and storage overhead, And dynamic batching incurs some CPU overhead.

Material settings for Batching:

Only objects that share the same material can be merged together. Therefore, if you want to achieve good batching, you must share as many materials as possible between different objects.

If you have two identical Materials, but with different texture maps, you can combine those texture maps into a larger map (often called a texture atlas ). Once the textures are in the same atlas, you can use a single Material override.

If you need to access the shared Material's properties from script, it's important to note that modifying  Renderer.material will create a copy of the Material. Instead, you should keep the Material shared       with Renderer.sharedMaterial .

When rendering shadow casters, even different Materials are often merged together. Shadow casting in Unity can even be dynamically merged with different Materials, as long as the required material properties in the shadow pass are the same. For example, many chests can use different texture materials, but for rendering texture shadow casters are irrelevant, in which case batching can be used.
      
Dynamic Batching:

Unity can automatically merge and dynamically merge objects that share the same Material and fulfill other criteria into the same DrawCall. Dynamic Batching is done automatically and does not require some additional work.

  • Merging dynamic objects has a per-vertex overhead, so merging is only used for Meshes that contain less than 900 vertex attributes in total.
        If your shader is for vertex position, normal and single UV, you can merge all vertices up to 300 meshes, conversely, if your shader is for vertex position, normal, UV0, UV1 and tangent functions, you can Merge all vertices into up to 180 meshes. Note: The limit on the number of properties may be changed in the future.
  • If the object contains a mirror image when transforming, it will not transform. For example, object A magnified by 1 times and object B reduced by 1 times cannot be merged together.
  •  Using different Materail instances, even if they are essentially the same, cannot be merged together, except for shadow caster rendering.
  •  Objects have additional rendering properties for lightmaps: lightmap index and lightmap offset/scale, so generally dynamically baked objects should point to the exact same lightmap location for batching. ).
  • Multi-pass Shader will break Batching.

        Almost all Unity Shaders support forward rendering of several lights, effectively doing more pass processing for them, and DrawCalls in additional per-pixel lights will not be batched.
        The light pre-pass rendering path of Legacy Deferred has been disabled for dynamic batching because it draws objects twice.

Since it transforms all object vertices to world coordinates on the CPU, it's only a small win for a DrawCall to draw, exactly how expensive a DrawCall is depends on many factors, mainly in the use of the graphics API, for example, in the console Or on modern APIs such as Apple's Metal, where the drawing overhead is usually much lower, regular Dynamic Batching doesn't do much.

Static Batching:
      
Static Batching allows the engine to reduce DrawCalls for geometry of any size (as long as it is not moving and has a shared material), it is more efficient than Dynamic Batching, it does not do vertex transformations on the CPU, but is more expensive more memory.
In order for static batching to be more efficient, you must explicitly specify that certain game objects are Static and will not be moved, rotated and scaled in-game. So you can check the Static flag in the Inspector panel.

Using static batching requires additional memory to store the merged geometry. If several game objects share the same geometry prior to Static Batching, a copy of the geometry will be created for each object in the Editor or at runtime. This will not always be a good approach, sometimes you keep the memory footprint small in order to sacrifice rendering performance by avoiding Static Batching. For example, using static trees in a dense forest level can have a serious memory impact.

Internally, static Batching works by transforming static objects into world space and then building a large vertex + index buffer for them. For visible objects in the same Batch, a series of cheap DrawCalls will be done with hardly any state changes between them. So strictly speaking it doesn't save "3D API draw calls (DrawCall)", but it saves the changes made by state transitions between them (which is extremely expensive).

      
Other Batching related tips

        Currently, only Mesh Renderers will be Batched. This means that Skinned Meshes, Cloth, Trail Renders and other types of render components will not be Batched.

        Semitransparent shaders often require objects to be rendered in a back-to-front order of transparency, and Unity gets the first command object in that order, and then tries to batch them. But because the order is strictly adhered to, it means less batching is easier to implement than opaque objects.

        Manually combining adjacent game objects is a good option for DrawCall Batching, for example, it makes sense to combine static drawers with a lot of detail into a Mesh, either in a 3D model application or using Mesh.CombineMeshes .

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326371317&siteId=291194637