Mark D
Mark D

Reputation: 576

Efficiently render a large number of Entities in RealityKit

How would I render something like 10,000 cubes efficiently in RealityKit, with the ability to animate each entities parameters like translation, scale, rotation independently?

If I try to add many entities to a scene, which all share the same ModelComponent, that ends up with one draw call per entity, which quickly slows down. In SceneKit if I add many SCNNode and share the same SCNGeometry then SceneKit will use instancing under the hood and only perform one draw call for many objects, but I can't seem to get RealityKit to do the same.

For example, something like this that draws a 10x10 grid of cube on the screen ends up with 100 draw call, even though the ModelComponent (mesh + materials) are all shared.

    let material = UnlitMaterial(color: .red)
    let modelComponent = ModelComponent(
      mesh: .generateBox(size: 0.1),
      materials: [material]
    )

    let containerEntity = Entity()

    for i in 0..<100 {
      let modelEntity = ModelEntity()
      modelEntity.model = modelComponent
      modelEntity.transform.translation = [
        -0.75 + Float(i % 10) * 0.15,
        -0.25 + floor(Float(i) / 10.0) * 0.15,
        0
      ]
      containerEntity.addChild(modelEntity)
    }

    let anchor = AnchorEntity()
    anchor.addChild(containerEntity)
    scene.addAnchor(anchor)

I know I could generate a custom MeshResource that has all the cube vertices defined in it and uses instancing instead, but then that makes things harder overall instead of just using the default Entity API provided by RealityKit.

I want to be able to animate the cubes and potentially apply some Physics to the models as well, so making a custom Mesh just makes that harder.

Thanks.

Upvotes: 3

Views: 370

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58143

Instanced Rendering

Unfortunately, at the moment there's no instanced rendering in RealityKit. So, this is the area where SceneKit definitely wins. RealityKit API has MeshResource.Instance object but it's misinterpreted (it's rather a mere sample than a lightweight copy of geometry). So if you have 10K cubes then you'll get 10K draw calls each frame. And nothing else.

In this form, rendering becomes a headache, because despite the fact that devices are becoming more and more powerful, iOS still has a limit on the number of polygons in the scene - there should be no more than 100K polygons per scene. This means that if you have 10K cubes, each of which has at least 12 polygons, you are exceeding the scene limit by 20K polygons.

ECS architectural pattern in RealityKit

Now regarding the animation of your cubes. This is where RealityKit's Entity-Component-System (ECS) paradigm comes into play. Systems can simultaneously work with several components and, using their update(context:) methods, can apply a logic to many entities that meet certain criteria. This allows developer to do any per-frame calculations for all grouped-by-criteria entities (not for every separate entity) only once per frame. You can deploy as many systems in RealityKit's scene as you want.

Upvotes: 2

Related Questions