Context:
What I am trying to do is create a PrototypeFactory I can use to produce copies of glTF loaded assets within my scene to create a 3D environment: use assetManager to load once, and reuse the glTF model everywhere. Things such as FloorTiles are in abundance and I’m trying to evaluate what would be the best performance
Question:
What are the pros/cons to the following cloning objects/meshes methods? I am trying to figure out the best approach that would cover the needs I have, but I don’t know what I loose/gain with each copy approach.
All this depends on the specific use case. Actually there is 3 possibilities to improve performance when you have a lot of identical meshes: clone, instance, thinInstance. For the best undestanding read this section - Copies, Clones, and Instancing | Babylon.js Documentation
For the whole GLTF model it is better to speak here about rootMesh.Clone(). But it is possible to use TransformNode as well.
Cloning is the “slowest” method (regarding the performance), but it allows to use different materials and even to change geometry in cloned meshes. Be aware that this method by itself will not clone neither skeleton nor animations (if there are any), you need to worry about it yourself.
Here is a small example with cloning GLB barrel model and changing clone’s geometry - https://playground.babylonjs.com/#4AJ16M#823
This method will create instance of the given mesh, but will not instance its children. In order to do that one needs to use rootMesh.instantiateHierarchy() - Mesh | Babylon.js Documentation
(and again, you may choose between cloning and instancing here with doNotInstantiate parameter).
This will not work, you need to iterate over all child meshes and position your thin instances through matrix operations. Example with 25 thin instances added to the same barrel PG example - https://playground.babylonjs.com/#4AJ16M#822 As one may see, the number of draw calls is the same (10) as here.
Thin instancing is the most performant way to render a huge number of identical meshes.
Regular instances still have a performance penalty on the javascript side because each instance is its own object (InstancedMesh): if you have 10000 instances in your scene, the engine must loop over all those objects to make a number of processing (visibility check, etc).
Thin instances don’t create new objects so you don’t incur any penalty on the javascript side by having thousands of them. This performance increase does come with a cost:
all thin instances are always all drawn (if the mesh is deemed visible) or none. It’s all or nothing.
adding / removing a thin instance is more costly than with InstancedMesh
Also, most of the functions which are enabled for ‘usual’ meshes and instances by default will not work for thin instances without enabling them specially. For example, to turn on mesh picking for thin instances there is thinInstanceEnablePicking parameter. Example - https://www.babylonjs-playground.com/#RC2IAH#1
Since all thin instances of a mesh are just one object, collisions also behave differently; one may need to use invsible collider.
Also, have a look at Thinnizator by @roland - https://forum.babylonjs.com/t/thinnizator-automatic-thin-instances/22120a
Summing-up:
Clones are the less performant but most flexible
Instances are the golden middle. all of the instances to share a material, again to manage draw calls, but remember you have custom buffers to pass information to specific instances. You can use the custom buffers to add variation to your instances as you can see in this Medium article.
Thin instances are the most performant after creation but have some limitations.