Click or drag to resize

Object Culling

The fastest way to render an object is not to render it at all. Object culling provides view-dependent performance improvements by only rendering visible objects. In many cases, only a subset of all objects are visible and a performance gain is expected. Although when all objects are visible, object culling may not improve performance.

Both primitives and globe overlays implement two types of culling:

To illustrate the performance gains of culling, we will do something that goes against the advice in the Batching topic - we will create lots of small primitives. The following code sample creates 1 degree extents covering the entire globe, a total of 64,800 triangle mesh primitives.

C#
private static List<Primitive> DrawGrid(int sizeInDegrees)
{
    CentralBody earth = CentralBodiesFacet.GetFromContext().Earth;
    Random random = new Random();
    List<Primitive> createdPrimitives = new List<Primitive>();

    for (int i = 0; i < 180 / sizeInDegrees; ++i)
    {
        for (int j = 0; j < 360 / sizeInDegrees; ++j)
        {
            CartographicExtent extent = new CartographicExtent(Trig.DegreesToRadians(-180.0 + (j * sizeInDegrees)),
                                                               Trig.DegreesToRadians(-90.0 + (i * sizeInDegrees)),
                                                               Trig.DegreesToRadians(-180.0 + ((j + 1) * sizeInDegrees)),
                                                               Trig.DegreesToRadians(-90.0 + ((i + 1) * sizeInDegrees)));
            SurfaceTriangulatorResult triangles = SurfaceExtentTriangulator.Compute(earth, extent);

            TriangleMeshPrimitive mesh = new TriangleMeshPrimitive(SetHint.Infrequent);
            mesh.Set(triangles);
            mesh.Color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
            mesh.Translucency = 0.0f;

            SceneManager.Primitives.Add(mesh);
            createdPrimitives.Add(mesh);
        }
    }
    return createdPrimitives;
}

The primitive manager automatically culls primitives and renders the scene in its default view at 5 fps as shown below. About half the primitives are not rendered due to horizon distance culling.

Object Culling Default View

When the view is changed, performance may increase substantially as shown below. From this view, both view frustum and horizon distance culling eliminate invisible primitives.

Object Culling Subset
Note Note

Technical Details: Primitives are put into a bounding volume hierarchy (BVH) which is used for hierarchical culling. The BVH is created using a surface area heuristic. The BVH is efficiently updated when a primitive changes position based on an algorithm in the 2007 paper Automatic Creation of Object Hierarchies for Ray Tracing of Dynamic Scenes. Removing primitives from a composite, and thus the BVH, is efficient and described in the Deletion in Bounding Volume Hierarchies blog post.

If instead of using lots of individual primitive, 72 TriangleMeshBatch objects from the Batching topic are created (one per unique color), the frame rate is between 149 and 445 fps. Unfortunately, there is tension between culling and batching. Culling is most effective with lots of small primitives, and batching is most effective with large objects that are generally visible. Ultimately, knowledge of your application should help you decide how to handle culling and batching.