I would like to change the colour of a material in from an operation, based on collision, but when I try to ‘set’ this attribute the new data is ignored. Instead I have to replace the entire material.
It looks as though, because the material’s colour is set from data registered on the GPU, setting the new emissive data would mean changing the registry to the new one, which doesn’t look like a straight forward problem to solve.
I can see a case for either
a) providing more than one material and switching it
b) making a class that can set the material where the entity is created but this seems to limit the kinds of workflow possible, and maybe makes them a bit more complicated.
There’re two “hacks” necessary to make your patch work
- the cache region must be forced to always execute
Ad 1) Just setting the descriptor on the material doesn’t do anything. One needs to call Material.New which in turn triggers the whole material builder pipeline. In Stride itself the materials are always created through its asset system, which does a little bit more than the plain Material.New so we had to write our own extension which also does that little bit more to have them work properly.
Ad 2) This is a longer topic, outlined here https://github.com/vvvv/VL.Stride/issues/240 - however the Cache region seems strange to me as well @gregsn@tebjan was this an oversight on our part? I mean it’s similar to our factory nodes / setter property change check issue just that here it was patched like that.
But in general modifying only certain properties of a material already came up internally and I’m not quite sure what the latest state on discussion was. I remember that the leaves in such a material graph (like the ColorIn) wouldn’t work anymore when they end up in two different sink materials. However those nodes are now implemented using ShaderFX so was this somehow magically fixed? @tebjan@untone
@Hadasi
to answer your title question, you have to clone the material and then change what should be different. but if you just clone it, the live inputs of the original material aren’t available anymore.
so for now, you can use one of the experimental nodes from the Materials category if you really have to do that:
they try to take care of this job.
but it is easier to just go with option a) and create two materials and switch them. the SetEmissive will also create a second material, so there isn’t that much won in using it.
another quick end easy way is to use instancing with the ColorPerInstance node to change the color of an individual object.
some background information: a material represents the whole render pipeline, not just the color. so when you modify a material, you potentially change the look of other models that are rendered with the same material/render pipeline. the material is kind of a big GPU render function that comes with parameters. right now we set these parameters where we create the function and we don’t provide a way to provide the parameters for the function at a later point / when it is rendered.
so actually, there would a third option: set the color (or another material property) in the draw call, just before rendering, but we don’t have nodes for that yet. you would need some kind of reference to the shader inputs and modify them just before rendering.
@tonfilm, thanks for the extra background. My desire is to animate that the colour change, so your last suggestion looks like the best option.
I guess a decent workflow could be to make a custom component that has this colour ref or any other attributes I would like to change and MyEntity .GetComponent<MyCustomMaterialDataComponent>() .colour.SetData<RGBA>(RGBA.FromHex('FFFF'))
Is it possible to patch a custom component at the moment?
It attaches a patch to the entity that you can retrieve somewhere else and interact with it. inside the patch script you can manage the material or any other property/component of the entity.