- Home /
Renderer with multiple materials -- per-material MaterialPropertyBlocks?
I am working with imported assets that have multiple materials per mesh (eg: a single MeshFilter and MeshRenderer, with the MeshRenderer's materials[] array containing 2 or more entries). Each Material has a unique albedo texture but shares other parameters with every other material. For Meshes that contain only a single material, I've been using MaterialPropertyBlocks to quickly change properties across every material. (I'm ingesting models from photogrammetry software, and adding overlays, different shading strategies, etc -- this is data viz in a game engine, not really a 'game').
This breaks when Models have two or more Materials, though -- I can only set a single MaterialPropertyBlock for the MeshRenderer, so Material[0] gets the correct albedo, but Material[1] through whatever end up sharing that albedo, which of course looks horrible since the UVs are all wrong.
To work around the issue I could create several shaders with texture samplers named eg _MainTex0, _MainTex1, etc, and make sure the variant with _MainTex1 is always assigned to materials[1], etc, but this seems like a silly hack.
Is there a "right" way to get this done?
Did you ever find a way to do this? Currently running into the same situation.
Answer by Glurth · Nov 26, 2017 at 07:56 PM
One workaround option is to call the Graphics.DrawMesh function, rather than using a MeshRenderer component. https://docs.unity3d.com/ScriptReference/Graphics.DrawMesh.html This function has versions that take a MaterialPropertyBlock, a Mesh, and a sub-mesh index. So, obviously, you would need to call this function once per sub-mesh.
In my experience, this is far less efficient (speed-wise) than using a MeshFilter and MeshRenderer.
I don't really LIKE this workaround, I'd rather be able to actually set a particular sub-mesh's MaterialPropertyBlock, and just use the Regular MeshRenderer, but I just don't see how- other than breaking up the mesh's sub-meshs into multiple "full" meshes (and putting them in the scene as their own GameObject, with their own meshFilter and meshRenderer).