Search Unity

Question How to implement culling with DrawMeshInstanced?

Discussion in 'General Graphics' started by TheSmokingGnu, Aug 30, 2021.

  1. TheSmokingGnu

    TheSmokingGnu

    Joined:
    May 1, 2017
    Posts:
    22
    In my game I use DrawMeshInstanced to draw all the objects. I am using ECS, so Transforms and other optional per-instanced data are stored in entities (each entity has a LocalToWorld component with a transform matrix). Each frame I iterate over all rendered objects, and gather their transforms into input arrays for DrawMeshInstanced - copying their transforms.

    On a benchmark vs using normal GameObject approach my system renders N objects in 16.6 ms vs 43ms by GameObjects. However, I do not cull objects in any way, so on the same scene in the situation when all objects are off-screen, GameObjects render frame in only 3.8 ms, while my system, as expected has no change at all.

    My question is, how do I implement objects culling to get similar boosts in my system?
    I tried adding a simple bounds check every frame using CameraFrustrumPlanes:
    For each object I do

    Code (CSharp):
    1. var bounds = group.SharedData.Mesh.bounds;
    2.             bounds.center = localToWorld.Position;
    3.             var inside = GeometryUtility.TestPlanesAABB(m_frustrumPlanes, bounds);
    4.  
    5.             if (!inside)
    6.                 return;
    With this, with all objects in screen, I am up to 25ms, and with none - down to 9.3. Maybe someone can explain how unity's culling works, or give some advice on how to add it to a manual DrawMeshInstanced system? Any other insights into possible problems of my approach are also appreciated.