Nodes/Pixar's OpenUSD/Apply USD Material
ComfyUI Node

Apply USD Material

Give a generated mesh a real PBR material, textures included

By cjhosken·Created 3 months ago·Updated 2 months ago· 9
Apply USD Material
  • USD
  • diffuse_color
  • emissive_color
  • USD
material_prim_path/Root/Materials/Material
mesh_prim_path/Root/Mesh
roughness0.50
metallic0.00
opacity1.00
ior1.50
diffuse_texture
roughness_texture
metallic_texture

This is the node you'll actually reach for. Apply USD Material builds a real, standard USD material - a UsdPreviewSurface with a full PBR parameter set - and binds it to a mesh. One node, and your generated object goes from "gray default plastic" to "has a color, a roughness, metalness, maybe a texture." UsdPreviewSurface is the USD interchange material that every renderer and DCC can at least preview, so this is the safe, portable way to dress up a mesh.

The typical flow: Convert USD turns a generated MESH into a stage, Apply USD Material colors and textures it, a light makes it visible, and Save USD ships it. If you only install one node from this pack's scene set, this is it.

The inputs

  • USD and mesh_prim_path (default /Root/Mesh) - what gets the material. Wildcards work, so you can bind the same material to a whole subtree.
  • material_prim_path (default /Root/Materials/Material) - where the material prim is created.
  • diffuse_color, roughness (0–1), metallic (0–1), emissive_color, opacity (0–1), ior (default 1.5) - the standard PBR knobs, all with sane defaults.

And the three optional texture inputs, which are the feature that separates this from "set a flat color":

  • diffuse_texture, roughness_texture, metallic_texture - either a bare filename or a full path.

When you give it a texture, the node builds the whole USD texture chain: a UsdUVTexture node, a UsdPrimvarReader_float2 to read the mesh's st UVs, and a connection into the preview surface. When you don't, it falls back to your constant values. So a mesh with UVs gets proper textured PBR; a mesh without them still gets a clean flat material.

How it works

Mechanically: it defines the material, defines the shader, sets the shader's id to UsdPreviewSurface, connects the shader output to the material's surface terminal, wires up any texture sub-graph, and then binds the material to each matched mesh via MaterialBindingAPI. All standard USD, all portable.

Install & the gotchas that actually bite

Pack install: ComfyUI Manager → search "ComfyUI-OpenUSD", or

cd ComfyUI/custom_nodes
git clone https://github.com/cjhosken/ComfyUI-OpenUSD

then restart. Deps: usd-core==26.5, numpy==2.5.0, trimesh.

Three traps, in order of how often people hit them. 1) Texture resolution is silent: a bare filename is looked up in ComfyUI's input folder, and if it can't be found, the node quietly falls back to the constant color instead of erroring. Your texture "not applying" is usually this. 2) Texture = no UVs = nothing maps: generated meshes often arrive without usable UVs (the 3D-generation ecosystem is famous for this), and then the texture wires up fine but maps nowhere. Check primvars:st exists on the mesh, or stick to constant colors. 3) The USD socket is pack-private - material output flows only through OpenUSD nodes.

Category3d/usd/scene

Inputs (12)

NameTypeDefaultDescription
USDUSD
material_prim_pathSTRING/Root/Materials/Material
mesh_prim_pathSTRING/Root/Mesh
diffuse_colorCOLOR#cccccc
roughnessFLOAT0.500–1
metallicFLOAT0.000–1
emissive_colorCOLOR#000000
opacityFLOAT1.000–1
iorFLOAT1.500–5
diffuse_textureoptSTRING
roughness_textureoptSTRING
metallic_textureoptSTRING

Outputs (1)

NameTypeDescription
USDUSD