How to create valid material/shader/sdr, and bind it to prim, in python

I’m writing a script to set and randomize the material/shader for any rigid body under DirectRLEnv. However I encounter 2 problems:

  1. The material I created is somehow invalid, and does not look like a complete one either. I get no idea how to create a valid and compelete one.
  2. I failed to bind the material with the prim after I create it.

Isaac Sim Version

5.0.0

Operating System

Ubuntu 22.04

GPU Information

  • Model: NVIDIA GeForce RTX 5090
  • Driver Version: 570.86.10
  • nvcc Version: Build cuda_12.8.r12.8/compiler.35404655_0Topic Description

Detailed Description

My script can be concluded as below:


from isaaclab.envs import DirectRLEnv
import omni
from pxr import UsdShade,Sdf
from isaacsim.replicator.behavior.utils.scene_utils import create_mdl_material

import random

class MyEnv(DirectRLEnv):
    def _setup_scene(self):
        # unrelated code omitted

        # 1. create material for my table
        mtl_path = "my_path/mdl/Aluminum_Anodized.mdl"
        prim_path = "/World/envs/env_0/RigidObjects/table/Looks"
        material = create_mdl_material(
            mtl_url=mtl_path, mtl_name="test_mtl", mtl_path=prim_path
        )
        
        # 2. randomization logic, e.g. on "diffuse_texture"
        _texture_urls = [
            "my_path/texture/wood_brown.png",
            "my_path/texture/linen_gray.png",
            "my_path/texture/concrete_gray.png",
        ] 
        shader_prim = omni.usd.get_shader_from_material(material, get_prim=True)
        shader = UsdShade.Shader(shader_prim)
        for shader_input in shader.GetInputs():
            if "diffuse_texture" in shader_input.GetFullName():
                diffuse_texture = random.choice(_texture_urls)
                shader_input.Set(diffuse_texture)

        # 3. bind material to prim
        stage = omni.usd.get_context().get_stage()
        prim = stage.GetPrimAtPath(prim_path)

        UsdShade.MaterialBindingAPI(prim).Bind(
                material, UsdShade.Tokens.strongerThanDescendants
        )

# FYI:
#  from isaacsim.replicator.behavior.utils.scene_utils import create_mdl_material
# https://github.com/isaac-sim/IsaacSim/blob/47d886f2858d1ceed556b21c88927aa67bc81c12/source/extensions/isaacsim.replicator.behavior/isaacsim/replicator/behavior/utils/scene_utils.py#L377
def create_mdl_material(mtl_url: str, mtl_name: str, mtl_path: str) -> UsdShade.Material:
    """Creates an MDL material at the given path with the specified URL and name."""
    omni.kit.commands.execute("CreateMdlMaterialPrim", mtl_url=mtl_url, mtl_name=mtl_name, mtl_path=mtl_path)
    stage = omni.usd.get_context().get_stage()
    mtl_prim = stage.GetPrimAtPath(mtl_path)
    shader = UsdShade.Shader(omni.usd.get_shader_from_material(mtl_prim, get_prim=True))

    # Create various material inputs
    shader.CreateInput("diffuse_texture", Sdf.ValueTypeNames.Asset)
    shader.CreateInput("project_uvw", Sdf.ValueTypeNames.Bool)
    shader.CreateInput("texture_scale", Sdf.ValueTypeNames.Float2)
    shader.CreateInput("texture_rotate", Sdf.ValueTypeNames.Float)

    return UsdShade.Material(mtl_prim)

Error Messages

[Error] [omni.hydra] Unable to find SdrShaderNode for prim: ‘/World/envs/env_0/RigidObjects/table/Looks/Shader’ with identifier: ‘9514733464790506132<table_material>’.

Screenshots or Videos

  1. If I manually bind the material onto my table prim in IsaacSim-Property-Material and Shader-Shader, it will turn RED:

  1. The invalid and incomplete Shader somehow works with the value I give it, but it still looks incomplete:

  2. Take a valid one for example, it seems to have more items:

Additional Information

Related Issues

I’ve read this: How to change properties of loaded material?. however the helpful links inside all turns invalid now.

So Glad You Could Help!

@2050313360 a few resources available mentioned in the other thread can be found here:

feel free to give those a try and see if that works for you.

and if it’s SDG-specific where you’d like to do randomization on material or texture, you can look into a couple helpful snippets:

@Simplychenable covered the relevant approaches in Posts #2 and #3. For quick reference, the standard pattern for creating and binding an MDL material in Python is:

  import omni.kit.commands                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                         
  # Create material                                                                                                                                                                                                                                                                                                                                                      
  success, result = omni.kit.commands.execute(                                                                                                                                                                                                                                                                                                                           
      "CreateMdlMaterialPrim",                                                                                                                                                                                                                                                                                                                                           
      mtl_url="OmniPBR.mdl",                                                                                                                                                                                                                                                                                                                                             
      mtl_name="OmniPBR",                                                                                                                                                                                                                                                                                                                                                
      mtl_path="/World/Looks/MyMaterial"                                                                                                                                                                                                                                                                                                                                 
  )                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                         
  # Bind to prim                                                                                                                                                                                                                                                                                                                                                         
  omni.kit.commands.execute(                                                                                                                                                                                                                                                                                                                                             
      "BindMaterialCommand",                                                                                                                                                                                                                                                                                                                                             
      prim_path="/World/MyMesh",                                                                                                                                                                                                                                                                                                                                         
      material_path="/World/Looks/MyMaterial",                                                                                                                                                                                                                                                                                                                           
      strength=UsdShade.Tokens.stronge rThanDescendants                                                                                                                                                                                                                                                                                                                  
  )                                                                                                                                                                                                                                                                                                                                                                      

See the Scene Setup Snippets — Materials docs for the full set of examples. If you’re still having issues, please open a new topic with the specific error messages. Closing this one.