CustomMaterial with different textures

Hi!

What could go wrong with the scenario below?

I have a code that works like this:

  • Load a mesh
  • Create new StandardMaterial and apply it to mesh

I have about 100 meshes and each have unique diffureTexture. Performance is good.

Then, the next version is this:

  • Load a mesh
  • Create new CustomMaterial and apply it to mesh

This time the performance gets very bad… it seems that CustomMaterial gets recompiled all the time or something.

I find many threads about cloning CustomMaterial already etc. but still could not find this exact issue. My initial idea was that plain CustomMaterial without any customization would be just like StandardMaterial… :thinking:

Could I somehow clone the CustomMaterial and change the diffuseTexture only without recompiling the whole shader?

It should definitely be possible to cache the shader and reuse the effect. Could you provide a quick repro in the playground I am worried we might have a cache issue ?

Maybe that can help:

1 Like

Here you go ( using my existing test-bench, it seems to catch multitude of bugs easily :smiley: ):

CustomMaterial, this uses 50% of CPU all the time and even FPS drops to 30fps when zooming:
https://playground.babylonjs.com/#U2KKMK#167

Same with StandardMaterial, no problems here:
https://playground.babylonjs.com/#U2KKMK#166

You should not create new materials continously but create a pool beforehands and get one from it when needed:

https://playground.babylonjs.com/#U2KKMK#170

2 Likes

Hmm… I am wondering how StandardMaterial handles this “out-of-the-box” without any performance hit?

For CustomMaterial to be as effective should it somehow cache the internal shaders globally instead of always recompiling them? I feel uncomfortable that just changing the material color would lead into implementing a pool etc.

I am also thinking this workaround: Should I just inherit my own material from StandardMaterial and change the shader code there?

Or 2nd idea: Could I create uniforms for material color and texturemap and use only single instance of CustomMaterial? For color I think I know how to do this but not for diffuseTexture… Edit: This seems to be difficult as CustomMaterial returns undefined for getEffect()… At least it seems that I totally misunderstand StandardMaterial and CustomMaterial relationship by just trying to use intuition :wink:

You will still have some perf hit because there’s a creation of a material each frame, so some GC will kick in at some times. It’s not as bad as with a CustomMaterial because the StandardMaterial is able to reuse an existing effect and not create a new one each time, something the CustomMaterial can’t do currently.

That’s basically what CustomMaterial is doing.

You can do something like that, but it is not really supported as the _uniformBuffer variable is not exposed:

https://playground.babylonjs.com/#U2KKMK#177

1 Like

Thank you! :slight_smile: This is just what I am looking for! I would be very happy to see this part of exposed API as well. I find it very usefull.

And about this:
const mat = new BABYLON.CustomMaterial(); // can also use StandardMaterial for that matter, no need for a CustomMaterial as no shader code is modified

… I do need to modify the shader in the real use case. That’s the exact reason to do this with CustomMaterial. :slight_smile: