maya-usd icon indicating copy to clipboard operation
maya-usd copied to clipboard

MaterialX mix_surfaceshader and nodedefs support

Open terracotta75 opened this issue 1 year ago • 7 comments

Describe the bug Here are 2 simple materialX files that fail to load in Maya 2026. With the first one, it appears that Maya can't load a mix_surfaceshader node. The second test file contains a custom nodedef, and Maya doesn't seem to succeed to load it. Both graphs are loading and rendering correctly in the MaterialX graph editor.

Steps to reproduce Test files are included in the repro package attached.

Error 1: Load test1.usd using the Create/USD/Stage from file menu in Maya

Error 2: Load test2.usd using the Create/USD/Stage from file menu in Maya

<?xml version="1.0"?>
<materialx version="1.39" xmlns:xi="http://www.w3.org/2001/XInclude">
  <nodegraph name="NG_Front">
    <standard_surface name="sss1" type="surfaceshader" xpos="-1.507246" ypos="-1.068966">
      <input name="base_color" type="color3" value="1, 0, 0" />
    </standard_surface>
    <standard_surface name="sss2" type="surfaceshader" xpos="-1.623188" ypos="0.043103">
      <input name="base_color" type="color3" value="0, 0.141809, 1" />
    </standard_surface>
    <mix name="mix_surfaceshader1" type="surfaceshader" xpos="0.347826" ypos="-0.094828">
      <input name="fg" type="surfaceshader" nodename="sss1" />
      <input name="bg" type="surfaceshader" nodename="sss2" />
      <input name="mix" type="float" value="0.5" />
    </mix>
    <output name="out" type="surfaceshader" xpos="3.463768" ypos="-0.112069" nodename="mix_surfaceshader1" />
  </nodegraph>
  <surfacematerial name="M_Front" type="material" xpos="19.449276" ypos="0.301724">
    <input name="surfaceshader" type="surfaceshader" nodegraph="NG_Front" output="out" />
  </surfacematerial>
</materialx>
<?xml version="1.0"?>
<materialx version="1.39" colorspace="lin_rec709" xmlns:xi="http://www.w3.org/2001/XInclude">
  <nodedef name="ND_ColorSelector" node="mycolorselector">
    <input name="input_choice" type="integer" value="0" xpos="11.985507" ypos="3.474138" />
    <output name="out" type="color3" />
  </nodedef>
  <nodegraph name="NG_ColorSelector" nodedef="ND_ColorSelector">
    <convert name="itof" type="float" xpos="14.347826" ypos="2.801724">
      <input name="in" type="integer" interfacename="input_choice" />
    </convert>
    <switch name="switch_color3" type="color3" xpos="16.391304" ypos="2.025862">
      <input name="in1" type="color3" value="0.625917, 0.162218, 0.162218" />
      <input name="in2" type="color3" value="0.0845045, 0.606357, 0.426452" />
      <input name="in3" type="color3" value="0.420308, 0.0878761, 0.599022" />
      <input name="in4" type="color3" value="0.0619018, 0.162952, 0.266504" />
      <input name="which" type="float" nodename="itof" />
    </switch>
    <output name="out" type="color3" nodename="switch_color3" xpos="19.695652" ypos="0.034483" />
  </nodegraph>
  <nodegraph name="NG_Test">
    <mycolorselector name="my_color_selector_1" type="color3" xpos="10.985507" ypos="0.577586">
      <input name="input_choice" type="integer" value="1" />
    </mycolorselector>
    <standard_surface name="ss" type="surfaceshader" xpos="13.449275" ypos="0.698276">
      <input name="base" type="float" value="0.8" />
      <input name="base_color" type="color3" nodename="my_color_selector_1" />
      <input name="diffuse_roughness" type="float" value="0" />
      <input name="specular" type="float" value="1" />
      <input name="specular_roughness" type="float" />
    </standard_surface>
    <output name="out" type="surfaceshader" nodename="ss" xpos="16.123188" ypos="0.577586" />
  </nodegraph>
  <surfacematerial name="M_Test" type="material" xpos="15.927536" ypos="1.405172">
    <input name="surfaceshader" type="surfaceshader" nodegraph="NG_Test" />
  </surfacematerial>
</materialx>

Expected behavior Screen shots of expected results and the errors are included in the repro package attached.

# Warning: Shader not found at </MaterialX/Materials/M_Front/NodeGraphs/sss1> for input "fg"
# Warning: Shader not found at </MaterialX/Materials/M_Front/NodeGraphs/sss2> for input "bg"
# Warning: Shader not found at </MaterialX/Materials/M_Test/NodeGraphs/my_color_selector_1> for input "base_color"

Attachments Repro package with errors and expected results attached.

Specs (if applicable):

  • Maya 2026
  • mayausd 0.31.0
  • MacOS Sequoia 15.4.1

Additional context Does mayaUSD support:

  • the mix_surfaceshader node?
  • nodedefs?

Thank you so much!!! <3

matx-issue.zip

terracotta75 avatar May 02 '25 23:05 terracotta75

For reference here is an example in the materialX Specification using both the mix node, and nodedefs: https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/documents/Specification/MaterialX.Specification.md?plain=1#L1495

terracotta75 avatar May 05 '25 16:05 terracotta75

Thanks for reporting. We will look into this.

wallworm avatar May 08 '25 18:05 wallworm

I've consulted the team and it appears that there is a mixture of MaterialX version mismatches as well as the fact that the USD MaterialX Loader does not handled embedded NodeDefs.

For the first file, you may see some better results by changing the version from 1.39 to 1.38, which will allow you to load the MaterialX in Maya... but it probably still won't work once referenced into USD because it's using a top level NodeGraph which USD doesn't like for referencing.

For the second file you will need to circumvent the USD limitation of embedded NodeDefs; instead of embedding, you can extract your NodeDef/NodeGraph for ColorSelector into its own MaterialX file and adding that file to both MATERIALX_SEARCH_PATH and PXR_MTLX_STDLIB_SEARCH_PATHS before being referenced.

I was informed this may not solve all issues but at least get you started on troubleshooting.

wallworm avatar May 09 '25 14:05 wallworm

Hi Shawn, thank you so much for looking into this!

About the version mismatch, I changed 1.39 to 1.38 in both mxtl files, and I'm getting the same result and same errors. So it doesn't look like I'm using any features that are supported only in 1.39.

The USD embedding layer wasn't on my radar, so I understand now how some mtlx files may load smoothly in the MaterialX Viewer, but would raise issues in Maya once referenced from a USD file. Thank you for bringing that to my attention.

But I'd love to understand both issues better.

test1

it's using a top level NodeGraph which USD doesn't like for referencing.

Please help me understand this one. If I modify the graph as show below on front_B, then the material loads and renders correctly in Maya:

Image

Both of those material have a top level NodeGraph though, don't they?

test2

you will need to circumvent the USD limitation of embedded NodeDefs

Hm ok, we could try that. We will define those env variables in Maya.env. Is there a chance that this limitation might get addressed at some point in the future? Fyi, saving the nodedefs in a different file is not our preferred option currently for the following reasons:

  • when the nodedefs contain images in a local folder, there is often issues finding those images later from the graph using the nodedef.
  • portability: if the USD stage gets handed off to someone else, the package isn't self contained, and the new user would need to set environment variables on their end, and import a library a nodedefs, which is not ideal.
  • in our current project, some of the nodedefs are specific to the project. Their purpose is to act like a subgraphs, to help breaking down a complex graph into smaller chunks. They may be reused within the same stage, but they are not meant to be reused in any other stage. So it makes sense for them to live in the project, rather than in a library.

We have also tried to use nodegraphs instead of nodedefs to define our "sub-graphs", but we ran into errors when trying to load in Maya, when a .mtlx file contains more than one nodegraphs.

By the way, if there is another communication channel that is more suitable for these discussions, please let us know!

Thank you so much!

terracotta75 avatar May 09 '25 22:05 terracotta75

Hi @terracotta75 , by top level dependency Shawn meant directly plugged in the Material node. For now the expected shading graph is : Material -> Surface -> NodeGraph (what you did in front_Fix)

Just to make sure I got it right, can you please share with us how you are using the MaterialX file with usd? From what you said, I would assume you're referencing it in your USD file.

derlerk avatar May 12 '25 14:05 derlerk

Hi @derlerk, OK I understand what you guys mean by top level nodegraph now.

Yes we are referencing the mtlx file, something like this:

#usda 1.0
(
    defaultPrim = "root"
)

def Xform "root"
{
    def Cube "Cube1"()
     {
     }
   
    def Scope "Looks"(
            prepend references = [
                @./front.mtlx@</MaterialX/Materials>
            ]
        )
    {
    }
}

So in summary, what I'm hearing is that those issues are not mayausd issues per say. They are more on USD's MaterialX integration side, where:

  • the material node can not be directly connected to a nodegraph's output
  • embedded nodedefs are not supported

Maybe I should continue this discussion in the OpenUSD repository instead then?

terracotta75 avatar May 13 '25 14:05 terracotta75

Exactly this involve the usdMtlx module. It's converting the Mtlx file to usd. You can find more info here : https://github.com/PixarAnimationStudios/OpenUSD/blob/dev/pxr/usd/usdMtlx/reader.h#L30 https://openusd.org/release/api/usd_mtlx_page_front.html

On the MayaUSD side we have another converter, that convert LookDevX MaterialX (MaterialX Stack in maya) materials to USD. https://github.com/Autodesk/maya-usd/blob/dev/lib/usd/translators/shading/mtlxMaterialXSurfaceShaderWriter.cpp https://help.autodesk.com/view/MAYAUL/2025/ENU/?guid=GUID-BCF8E14C-6347-4CF8-9CD4-FA3E6CAFD8BA

derlerk avatar May 13 '25 15:05 derlerk