I have instances with instance buffers.
Some of the instances are mirrored.
They are then renderered without instancing which is fine.
I have my own variant of PBRMaterial. For instances is uses instance buffers to feed in per-instance data. For the few non-instances I wanted to have feature-parity so I store the value elsewhere in the mesh (it was not allowed to have instance buffers on non-instances!). I bind to the material for each draw in afterBind. See Babylon.js/pbrCustomMaterial.ts at master · BabylonJS/Babylon.js · GitHub for a reference.
This works well for my non-mirrored instances and my regular objects.
The mirrored instances though end up as non-instances and they get the non-instanced Effect. So far so good. But the mesh that is send to afterBind is not the InstancedMesh where my metadata / instance-data resides. Instead it is the Mesh that is used to render it (the sourceMesh I guess).
Can someone think of a workaround so I can find my meta-data?
Cheers!
I would recommend to do it a bit differently.
Create 2 instance pools
One for the mirror and one for the main one
So you can simply use instances all the time
Ha yeah that is the system I am building. hence my PRs One to be able to have a mesh as source mesh multiple times without massive memory overhead and the other one to move instance between source meshes. Guess I’ll try to get the determinant into that pooling system together with material and recieveShadows (the two attributes I have right now to decide what pools an instance goes into).
It does feel like babylon should do this internally though. If we think of a material holding multiple permutations of a shader, an InstancedMesh could compute a feature-set (material, recieveShadow, transform-mirror, …) and choose from pool of instance-buffers to populate. That would be easier than me having to write that system on the outside and I think it would end up quite neat.
It would also solve the issue where it is hard to transition an InstancedMesh into a Mesh (when you only have one) since there really is no difference between them (since there is a virtualization between Mesh-node and actual geometry anyway). Food for thoughts!
I agree but it is a bit work (in term of CPU) and honestly I really try to keep the CPU as low as possible as a lot of BJS experiences are CPU bound
In this case, you know exactly how to create the two pools and I agree it is a bit more complex but realistically faster to execute
Agreed. I think that CPU cost would be minimal as the only operations that would have any cost associated to them would be operations that can’t be done on instances (change material, change recieve shadows, change transform winding).
I would probably structure it as… if any of those change I set a dirty flag. Then at draw-time if it is dirty it fetches the appropriate Geometry-object from the sourceMesh (that is now something else and not a Mesh… more like a geometry with variants).
And then you render as usual. Cull/draw and add into instance buffer of the geometry that matches what you need. So draw per frame would be as low as what we have now.
But it is a lot of work of course so now saying it should be done, just think it could be done at a very low CPU-cost.
1 Like
Let’s merge your current PR and we could chat about that as next step for sure!
btw, thanks a lot for your help and contributions!
1 Like