passing float value to shader not creating new material instances [SOLVED]

I have a problem, that i have on the scene 5000 shadow casters with their unique material instance. I got an Idea to put all those textures into one 4k texture as I need only 1 bit for information as I use alpha test. But I need to pass some data to the shader like object’s UV offset (as it will be atlas) or layer, channel. So basically I need to pass some floats to the shader, but I have no clue how to not make new material instances as I would do it as a property. Also I read if I use uniform values it would not work nicely if I need to render more objects with different float values at same time. So do you have any idea?

Thanks

Modifying the material in a renderer will create a new material instance (ex. myRenderer.material.SetFloat(…))

Modifying the shared material in a renderer will apply that change to the material in your project folder, so no new instances are made and the change applies to every renderer with the material (ex. myRenderer.sharedMaterial.SetFloat(…))

One thing to keep in mind is that changing a shared material modifies the material in your project, and those changes are not undone when you leave play mode. Be sure to set your materials back to defaults at the start of your program, if necessary.

My mistake… I see you’re trying to do that with uniforms, not properties… I think you’d have to use static functions from the GL class, but I haven’t done anything like that in Unity.

Thanks I know, I work with shaders a little bit. But now I want to do something like to pack textures into atlas and say this object takes this UV part this object has this offset and so… And Why I am doing it is to reduce number of materials. Only problem is, that I need to tell shader where to take values for each object from that texture. If I change property in material - it makes a new instance. If I set float as you said It change whole shader for all objects… But there must be a solution, otherwise no dynamic atlases could be made. Or How do I can make a trick? Well I could somehow encode these values into second map, and read it… but It is too nerdy :smile:

I don’t know how many unique meshes you’re using or how complex they are, but perhaps you could loop through the UVs on each mesh and map the UVs to fin within the range of the object’s texture within the atlas. It would be a small pain, but maybe if you reference the mesh right out of your project folder, you can save the changes so you only have to do it once (not per-run, though you’d have to redo this process if you alter the atlas).

it is around 5,500 meshes. I calculated that I can save up to 8 000 256*256 1bit textures into single 4k texture. I only need to know bit of color and UV position. I need only data for alpha tests as they are only shadow casters… no need to store 5000 32bit textures sending to gpu one by one… Also they are made dynamicaly after game starts so I cannot manually set UVs… But I will know UV positions and bits for each object, but dont know how to pass these data to shader…

It’ll only set properties, but it seems a MaterialPropertyBlock will allow you to set per-object properties while still allowing the objects to use the same material. You interact with a property block through code mostly the same way you do with a material, then you call SetPropertyBlock() on the renderer.

yes you are right. https://ctrlv.cz/ddcE here is a result (many bugs still) but you are looking on 5000 tree shadow casters and shader reads it without problems :slight_smile: Thanks a lot.

No problem, I learned something too :smile: