Collection based material assignments

   4796   9   2
User Avatar
Member
7734 posts
Joined: Sept. 2011
Offline
I can't seem to get collection based material assignments to work. The help says that when a collection is used as the bind target, it will be reused by the material bind collection. When I leave the collection prim blank as is indicated by the help is proper, I get an error:

Error 
Failed binding material.

Warning
Can only append a property 'material:binding:collection:spheres' to a prim path (/)

Warning
Cannot create relationship at invalid path </.material:binding:collection:spheres>

If I put in the prim that contains the collection used for the prim pattern I get a warning, and it still does not bind, however the usda looks like it might correct.

Warning 
Cannot set metadata. Failed to create spec </collections.material:binding:collection> in layer @anon:0x7efd6bf24c00@

Using an explicit prim list instead of a collection with collection based assignment only works if the collection prim already exists, and is an ancester prim of that which is being assigned. The node will not create a new prim to contain the collection. If an existing collections prim is used, the binding is created but does not work. Even in the case of an ancester prim being used for the collection and it working in the viewer, I am still seeing a warning:

Warning 
Cannot set metadata. Failed to create spec </shapes.material:binding:collection> in layer @anon:0x7fcdf4424d80@

Am I right to assume that collection based assignments only work when located in ancestor prims of those in the collection?

This would make the /collections and %foocollection workflow kind of useless for material assignments, as collections would always need to be localized.

I've attached example output from when I used an existing collection created by the collection lop for the collection based assignment and /collections is used as the collection path.

Edit:

/collections based collections and %foo syntax do work when used as the prim pattern for collection based assignments, but only when the destination prim for the collection is an ancestor of the collected prims. This creates a collection that ‘includes’ the /collections.foo collection instead of redundantly duplicating it which is nice. I still see the warning as above though. I think the help should be more clear that only ancestor prim collections will by considered by hydra and that a blank path for the target collection is never valid.
Edited by jsmack - Jan. 3, 2020 23:24:58

Attachments:
bandc.usda (1.8 KB)

User Avatar
Staff
1448 posts
Joined: July 2005
Offline
jsmack
Am I right to assume that collection based assignments only work when located in ancestor prims of those in the collection?
Yes, you are right. The USD standard says that the collection-based material binding relationship binds the “Material to all of the prims identified by the Collection that live beneath the binding relationshp's prim”
http://graphics.pixar.com/usd/docs/UsdShade-Material-Assignment.html [graphics.pixar.com]

It is re-iterated in the USD documenation that “A gprim and each of its ancestor prims can possess (…) collection-based bindings to Materials”

It's formulated like that for performance reasons. Ie, so that material discovery for a particular primitive does not require traversal of the whole scene graph, but just the direct ancestors.

For the remaining issues, I've submitted Bug 102011 to fix:
- theerror when collection prim path is empty
- the issue with LOP will not creating a new prim to contain the collection
- the warning about "Failed to create spec
- help info about binding on an ancestor
User Avatar
Staff
1448 posts
Joined: July 2005
Offline
These issues should be fixed in H18.0.344.

A few notes, however:
- The Assign Material LOP still will not create a new primitive to own the collection and define the material binding. The rationale is that if there is no primitive, then there cannot be any children. And, as already noted, the binding applies only to such prim and its children. So creating a prim is pointless in a way. It's probably better to alert the user that there is no primitive to define the binding on.
- The Assign Material LOP has a new feature, in that if the primitive path is empty, the LOP will try to automatically find the ancestor primitive common to all specified primitives. However, if such anestor is the root primitive, it will report an error, since it's not possible to create (material binding) relationships on the root.
Edited by rafal - Jan. 8, 2020 12:15:05
User Avatar
Member
12427 posts
Joined: July 2005
Offline
rafal
if the primitive path is empty, the LOP will try to automatically find the ancestor primitive common to all specified primitives

This sounds good (I think) but it might be good to generate a warning saying that it's engaging in this behaviour, perhaps with results inline?
Jason Iversen, Technology Supervisor & FX Pipeline/R+D Lead @ Weta FX
also, http://www.odforce.net [www.odforce.net]
User Avatar
Staff
1448 posts
Joined: July 2005
Offline
jason_iversen
it might be good to generate a warning
Done in H18.0.345
User Avatar
Member
7734 posts
Joined: Sept. 2011
Offline
Revisiting this, I'm able to create the binding, but it doesn't seem to work in karma or prman. Is this a feature that's not implemented in Hydra yet?

I'm testing in 18.0.597

generated usd looks like:

def "foo1" (
prepend apiSchemas = ["CollectionAPI:pxrsurface1"]
prepend references = @somecoolmodel.usd@
)
{
uniform token collection:pxrsurface1:expansionRule = "explicitOnly"
rel collection:pxrsurface1:includes = [
</foo1/shapelyShape>,
</foo1/frumpyShape>,
]
rel material:binding:collection:pxrsurface1 = [
</foo1.collection:pxrsurface1>,
</foo1/materials/pxrsurface1>,
]

def Scope "materials"
{
def Material "pxrsurface1"
{
token outputs:ri:surface.connect = <foo1/materials/pxrsurface1/pxrsurface1.outputs:bxdf_out>

def Shader "pxrsurface1"
{
uniform token info:id = "PxrSurface"
color3f inputs:diffuseColor = (0.5, 0, 0,5)
token outputs:bxdf_out
}
}
}
}
Edited by jsmack - Nov. 11, 2020 20:38:36
User Avatar
Member
260 posts
Joined: Nov. 2014
Offline
when i was asking about collections in another thread, i did test if first with this assignment, that worked fine:
is that valid approach?
Edited by martinkindl83 - Nov. 11, 2020 23:37:30

Attachments:
collections.png (16.9 KB)

User Avatar
Staff
4435 posts
Joined: July 2005
Offline
@jsmack, I've set up a hip file that basically authors the same setup you describe, but using a USD Preview Surface shader, and it seems to work fine… File is attached.

@martinkindl83 That should work fine, though it will actually create direct bindings on each geometry prim to assign the material one prim at a time. This isn't necessarily a bad way to work, but might make certain kinds of overrides/edits more complicated than using a true collection based material assignment.

Attachments:
collection_mat_assignment.hip (90.8 KB)

User Avatar
Staff
1448 posts
Joined: July 2005
Offline
@martinkindl83 As Mark pointed out, the setup shown in the image will create direct binding on each primitive in the collection. But if you expand Material Binding group and set the Method to “Collection Based”, then the LOP will use the collection you specified and create binding on a single parent primitive.

Both “Direct” and “Collection Based” method are perfectly valid and have their place in various use cases.
Edited by rafal - Nov. 12, 2020 11:07:25
User Avatar
Member
7734 posts
Joined: Sept. 2011
Offline
mtucker
@jsmack, I've set up a hip file that basically authors the same setup you describe, but using a USD Preview Surface shader, and it seems to work fine… File is attached.

It seems to work fine in 18.5. I guess it's not working in 18.0.597 for me for whatever reason.
  • Quick Links