Is there an equivalent to Unreal Engine's instanced materials in Babylon?

In Unreal, instanced materials allow you to specify parameters that can change during runtime. To update the value, the C++ code looks like this:

MaterialInstanceDynamic->SetScalarParameterValue("MyParameter", myFloatValue);

“MyParameter” is defined in the material and can drive anything you want, from emissive color to texture panning speed. The idea is you have a single material that can be applied to multiple instances, but each one can look different.

We can have multi material which internally share the same effect and shader (making them instances somehow)

Is that what you are looking for?

Material Instances appears to be a mechanism to avoid writing shader code when you want to modify an existing material’s properties without incurring shader compilation. To do so with Unity’s Material Instances, you have to use Dynamic parameters and avoid Static material parameters.

A big thing that makes material instances special is the ability to have parameters. One equivalent in Babylon is a custom material, one that has “attributes”. Another aspect of material instances is Inheritance documented under the second section header. I don’t think Babylon has a direct equivalent to material inheritance beyond that provided by JavaScript itself.

Babylon has ShaderMaterial, CustomMaterial, PBRCustomMaterial, Node Material Custom Blocks, and Material Plugins.

CustomMaterial is “a StandardMaterial with some customizable Options” while ShaderMaterial “is really meant for raw shader code and is only a thin layer above such code.”

Here is an older forum post with options for creating an NME material that uses attributes, including Node Material Editor Custom Blocks.

Shader Material allows you to define a custom shader with parameters, though the terminology is slightly different: “The vertex data for position, normal and uv coordinates are passed to the Vertex Shader as variables of category attribute. User data can be passed to both the Vertex Shader and the Fragment Shader as variables of category uniform. Data can be passed from the Vertex Shader to the Fragment Shader with variables of category varying.”

Unity’s Material Instance parameters appear to be limited to already-defined material parameters, though you can use Material Parameter Expressions to essentially expand beyond straight “material property = parameter value” into “material property = expressionAsFunction(parameter value,…)”.

There are complications when trying to use a shader material that comprehends different values for mesh instances because instances share vertex data, and vertex data is the underlying mechanism for supplying shader material attributes. I don’t know if/how Unity’s Material Instance addresses that issue.

Mesh thinInstances can have attributes that are passed to the shader material (or, I think, custom NME block). Here an example using color.

I can’t quite decode whether Unity’s Material Instances have the equivalent of the Shader Material’s “uniform.” A uniform is a constant for all meshes using that specific instance of material, but a uniform can be modified (for all meshes using it) without shader recompilation. As opposed to Unity’s Material Instance having Static Parameters which when changed do recompile the shader.

I hope this helps! Note that I got all this information from the links above. I’m kind of a “well-read newbie,” so an expert might come along and correct some of this.

3 Likes

Wow! There definitely looks to be some promising ideas in there, so I’ll pore over this and see if I can get something working. @deltakosh @HiGreg thank you for the suggestions.

Great summary!

1 Like

I found something that kind of works. Here is the PG:

The createMaterial code was generated from this node material:

After reading @HiGreg’s post, I decided to look more into the node material editor and found this blog post:

Unfortunately, it appears to be limited to the name “color” and the orange mesh.color node, i.e:
mesh.registerInstancedBuffer("color", 4);

I couldn’t find a way to add, say, a white Color4 input, give it a custom name, and register it on the instance buffer. The code ran, but it appeared to have no effect. If that worked, then I think it would be pretty close to the Unreal functionality because then you could add as many attributes as you wanted and have them drive different things.