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.

4 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!

2 Likes

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.

1 Like

Is there a way to do something similar for imported meshes? @babylon

Can you share what you are trying in a tiny Playground @Caner ? cause you can already clone/update imported materials, so a repro would help targeting the best behavior for your case.

Sure, here it is https://playground.babylonjs.com/#5GD63H#1

I am assuming I need to replace the materials with node material equivalents, and set mesh instance buffers for properties. But I am curious if various kinds of features will be available: not only colors and textures but also unlit, wireframe and alpha/transparency modes etc.

This is to use the advantages of instances, and still be able to make material modifications. Also left a question mark for skeletons and morph targets in the PG.

Thank you!

yup this will need to be highly custom as all the data (different) needs to come from an attribute. Currently only the TRS data + color (albedo) are instanced based. All the rest is global. NME does not imply where the data come from so it should not be too hard to build as long as the material variant is identical.

Regarding animations unless you are relying on a system like VAT, all instances would play the same frame.

2 Likes