Adding additional MeshInstances to Model


#1

Hello,

Is it possible to update the graph of a model during runtime, adding additional mesh instances?

Tried the following code, though it didn’t work:

var box = pc.createBox(this.app.graphicsDevice);
var node = new pc.GraphNode();
node.setPosition(
    pc.math.random(-this.boxDimensions, this.boxDimensions),
    pc.math.random(-this.boxDimensions, this.boxDimensions),
    pc.math.random(-this.boxDimensions, this.boxDimensions)
);

var material = this.material.resource;
var meshInstance = new pc.MeshInstance(node, box, material);
this.parentEntity.model.model.graph.addChild( node );
this.parentEntity.model.model.meshInstances.push(meshInstance);

this.app.scene.update();

#2

Hm… It might be a bit of a problem doing that way. Why you simply not add it as another child entity with model component?


#3

You are right it works that way. I was doing some stress tests to see the performance impact of entities, graphs, models etc and find the best way to reduce draw calls / memory allocation for static geometry. A way to merge geometry/models together.


#4

Each meshInstance - is a draw call actually. So by adding another mesh instance is same as having another entity with own mesh instance, in terms of rendering performance. There will be tiny more overhead indeed, but we talking here tiny micro-optimization in most cases. In most cases 99% of CPU pressure will come from other things and actual game logic.

Dev tools have Profiles tab, with CPU profiling - really useful tool to see what is actually taking most performance out.


#5

@max each mesh instance is a draw call, even if two mesh instances share the exact same material?


#6

If they share same message, it still need to dispatch a “draw” with some uniforms that are unique per each mesh instance, like their world matrix (transformation). If they are same, then they will share same vertex and index buffer and more likely avoid a lot of state changes including less changes of uniforms for program (shader) as they share material.

In order to avoid a draw call, either they have to be joined into single mesh instance by merging index buffer. Or by using instancing. But instancing only worth if you’ve got large number of same entities - then it can really help to reduce number of CPU > GPU instructions. But this is subject to case to case, and requires actual testing to identify if it will worth it.


#7

@max is there a PlayCanvas API for instancing?


#8

There are two approaches, but we endup not recommending both of them as through our tests performance was not changed in positive way.

One way is to enable simple auto instancing, and that is naive approach. All needed is to enable enableAutoInstancing on GraphicsDevice:
app.graphicsDevice.enableAutoInstancing = true

But again, this very likely not going to improve performance.

And other way is to manually control instancing, by managing array of uniforms to be passed to the instancing shader, but current implementation is not in usable state and will be removed/changed to a better API.


#9

Can it be possible to add additional mesh instances if they are skinned? The key problem with adding another entity is animation component not playing the animation on all the mesh instances, but instead you would need a model and animation component per entity.