Set shader uniform per object without duplicating the material

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Boulougou

I have a spatial shader with a uniform parameter, that I would like to set to a different value for each object. Is it possible to do it without duplicating the material for each object?

For example, godot sets the WORLD_MATRIX uniform to a different value for each object, even if multiple objects share the same material. I would like to do something similar but with a custom uniform.

:bust_in_silhouette: Reply From: Zylann

It is currently not possible to do that. Also, to do it the same way Godot does, you would have to be able to set that parameter before rendering, inside the rendering thread, and on the fly, because if you were to modify the material in any way, that would apply to all other objects using that material.

There could be room for a feature like this in the future, here is how I see it could be done:
That would be similar to what is found is Unity as “Property Blocks”. It’s like regular material parameters, except you set them on the node instead (MeshInstance for example) and they override material parameters. This way, it’s per-object, without having to duplicate the material, and the material remains unmodififed.

Although, I wonder why you think this is different than duplicating the material in Godot? The same shader would be used, just with different parameters, like you wanted, however there could be various reasons ranging from performance to workflow efficiency. For which reason do you want that feature?

For such a feature to be integrated one day, the first step would be to make a feature request on Github and explaining why it’s useful.

My use case is to render several different meshes with a transparent material, but I want the ALPHA value set by the pixel shader to be defined per object. Setting the ALBEDO alpha channel in the material works, but affects all other meshes.

Duplicating the material for each object would do it, but with two drawbacks:

  • After duplicating the material you can no longer change a material property and have an effect on all objects using it (you have to apply the same change on all the duplicates)
  • Having many objects with their own material copy might affect performance (it might not, depends on how godot handles this internally).

I will consider opening a feature request. Thanks!

Boulougou | 2019-07-06 06:48

Note that this proposal can only apply to uniform parameters. ALPHA isn’t one, but you might need to use a backing uniform float transparency; in your shader and then override that one.

Zylann | 2019-07-06 15:38