Setting property on URP overriden material

Hi - I am creating a basic thermal vision camera in URP. I have set up a second Forward Render (called ForwardHeat). This has a Render Objects on it, with an overriden material (HeatMaterial). HeatMaterial has a exposed parameter called _Heat.

In my scene, each object will have it’s own materials for usual rendering, however when I switch on a camera using the new ForwardHeat Renderer, I would like to be able to set the _Heat parameter. Ideally I should be able to set the value for each gameobject.

I am able to set parameters for materials attached to objects for their default rendering. However I cannot work out how to set a parameter for the overriding material.

There appears to be no way to access this via script from anything attached to the gameobject (it is unaware of anything other than normally attached materials).

I cannot see anything exposed in the render object where I can set parameters, let alone request info from a gameobject.

I have begun to look into the camera and Universal Additoinal Camera Data, however cannot find the overriden material in there. If I could, would I be able to set the value for each object on a single overriding material, or would every object have the same _Heat value?

Would appreciate any help provided! I cannot see anything in the help or using google searches!

Nevermind - in case anyone comes across this it’s actually very easy, using MaterialPropertyBlock:

MaterialPropertyBlock block = new MaterialPropertyBlock();

Renderer r = GetComponent<Renderer>();

r.GetPropertyBlock(block);
float random = Random.value;
block.SetFloat("_Heat", random);
r.SetPropertyBlock(block);

This appears to get the ‘active’ renderer rather than the one attached to the gameobject. An added bonus is that it does not complain if you set a parameter that does not exist in alternate materials

4 Likes

MaterialPropertyBlock is indeed probably the best way if you want per object overrides, but be aware that this is not compatible with the srp batcher and pretty much draw each object as it’s own draw call batch.

GetComponent always gets another component on the same object it is called on. So it does definitely get the renderer component attached to this gameobject.

If you want to override parameters for just the one HeatMaterial with the parameter being identical for all objects you could just expose it on a component as public Material and use SetFloat there. You could even keep it private and find it with Assetdatabase.FindAssets. Would be more efficient for the rendering.

Great, thanks Fleity, yes I guess I’ll have to put up with each object making it’s own draw call. Objects with heat will have their own heat values, I thought about using say 5-10 materials to create bands of heat, override using layers or something, but the added complexity means I’ll prob stick with the extra draw calls.

You’re my hero. The documentation around Render Objects is severely lacking!