Assign materials to GeomSubSets in instances?

Hej,

We are having a lot of rather big meshes with GeomSubSets to apply different materials to sub parts. In our stage we want to have the same mesh many many times but assign different colors to the GeomSubSet for each imported mesh. This works fine if but fails if we use “instanceable = true”.

Is there ANY way to assign materials to GeomSubSet on instanced meshes? We would really like to use instancing to reduce the memory usage of our scenes.

Here is an example that shows the problem we are having. The plane.usda contains a Mesh with two GeomSubSets

#usda 1.0
(
    defaultPrim = "plane"
)

def Xform "plane"
{
def Mesh "mesh"
{
    uniform bool doubleSided = 1
    float3[] extent = [(-0.5, 0, -0.5), (0.5, 0, 0.5)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 5, 4]
    point3f[] points = [(-0.5, 0, 0.5), (0.5, 0, 0.5), (-0.5, 0, 0), (0.5, 0, 0), (-0.5, 0, -0.5), (0.5, 0, -0.5)]

    def GeomSubset "color_change_1"
    {
        uniform token familyName = "materialBind"
        int[] indices = [0]
    }
    def GeomSubset "color_change_2"
    {
        uniform token familyName = "materialBind"
        int[] indices = [1]
    }
}
}

Then in our main.usda we import it twice, once as normal reference and once instanced and the color change works for the “normal” reference but not for the instanced one

#usda 1.0

def "plane_ref" (
    prepend references = @plane.usda@
    prepend apiSchemas = ["MaterialBindingAPI"]
)
{
    rel material:binding = </mtl/red>
    double3 xformOp:translate = (-1, 0, 0)
    uniform token[] xformOpOrder = ["xformOp:translate"]

    over "mesh" {
        over "color_change_1" {
            rel material:binding = </mtl/blue>
        }
    }
}

def "plane_inst" (
    instanceable = true
    prepend references = @plane.usda@
    prepend apiSchemas = ["MaterialBindingAPI"]
)
{
    rel material:binding = </mtl/red>
    over "mesh" {
        over "color_change_1" {
            rel material:binding = </mtl/blue>
        }
    }
}

def Scope "mtl"
{
    def Material "red"
    {
        token outputs:surface.connect = </mtl/red/red.outputs:surface>
        def Shader "red"
        {
            uniform token info:id = "UsdPreviewSurface"
            color3f inputs:diffuseColor = (1, 0, 0)
            token outputs:surface
        }
    }

    def Material "blue"
    {
        token outputs:surface.connect = </mtl/blue/blue.outputs:surface>
        def Shader "blue"
        {
            uniform token info:id = "UsdPreviewSurface"
            color3f inputs:diffuseColor = (0, 0, 1)
            token outputs:surface
        }
    }
}

Hey @olihey ,
The good news is that the object model for material binding definitely allows for this. The way you’d do it is by using a Collection-based Material binding(s) on some ancestor prim of the instance, targeting the GeomSubset prims under the instance , by path, and (important!) setting the BindingStrength on the binding relationship to "strongerThanDescendants"

The imperfect news is that we have yet to implement the "strongerThanDescendants" behavior for instances yet in Hydra, and I’m not immediately positive where it is on the roadmap. Please do file an Issue with your need for the feature - thanks!

OK, I was reminded by @raja that we have even better news! As described in Issue 1571, the material binding strength issue has already been addressed in “Hydra 2.0” . The referenced issue has instructions for turning it on, and we hope to enable it by default very soon now. For most needs it should be fine to enable it using the env var in 25.05 .