Usage Examples#

Add and Check MDL Modules in Registry#

import omni.UsdMdl as UsdMdl
from pxr import Sdf, Ar
import os

# Get asset path for an MDL module
module_path = "/path/to/material.mdl" 
asset_path = Sdf.AssetPath(module_path, Ar.GetResolver().Resolve(module_path))

# Check if a module is already loaded
if not UsdMdl.RegistryUtils.IsModuleLoaded(asset_path):
    # Only try to add the module if it exists (to avoid errors)
    if os.path.exists(module_path):
        # Add a single module to the registry
        success = UsdMdl.RegistryUtils.AddModuleToRegistry(asset_path)
        print(f"Module added successfully: {success}")
    else:
        print(f"Note: Module does not exist: {module_path}")
        print("Replace with a valid MDL file path in production code.")

# These operations would need valid MDL files to execute without errors
print("\n# Example code for use with real MDL files:")

# Add multiple modules at once
module_paths = [
    Sdf.AssetPath("/path/to/module1.mdl"),
    Sdf.AssetPath("/path/to/module2.mdl")
]
print("module_paths = [Sdf.AssetPath(...), ...]")
print("success = UsdMdl.RegistryUtils.AddModulesToRegistry(module_paths)")

# Get available subidentifiers in a module
print("subidentifiers = UsdMdl.RegistryUtils.GetSubIdentifiersForAsset(asset_path)")
print("for subid in subidentifiers:")
print("    print(f\"Available subidentifier: {subid}\")")

Create USD Shader with MDL Source#

import omni.UsdMdl as UsdMdl
from pxr import UsdShade, Sdf

# Create a USD shader with MDL source
def create_mdl_shader(stage, prim_path, mdl_module_path, subidentifier):
    # Create a Shader prim
    prim = stage.DefinePrim(prim_path, "Shader")
    usdshade_shader = UsdShade.Shader(prim)
    
    # Set the MDL module as the source asset
    source_asset = Sdf.AssetPath(mdl_module_path)
    usdshade_shader.SetSourceAsset(source_asset, UsdMdl.Tokens.Mdl)
    usdshade_shader.SetSourceAssetSubIdentifier(subidentifier, UsdMdl.Tokens.Mdl)
    
    # Get the shader node for this prim
    sdr_node = UsdMdl.RegistryUtils.GetShaderNodeForPrim(prim)
    if sdr_node:
        # Apply metadata from the shader node
        usdshade_shader.SetSdrMetadata(sdr_node.GetMetadata())
        
        # Create parameter inputs based on shader definition
        for name in sdr_node.GetInputNames():
            prop = sdr_node.GetInput(name)
            sdf_type = prop.GetTypeAsSdfType()[0]
            # Create input and set default value
            input = usdshade_shader.CreateInput(name, sdf_type)
            default_value = prop.GetDefaultValue()
            if default_value is not None:
                input.Set(default_value)
    
    return usdshade_shader

# Example usage:
# stage = get_current_stage()
# shader = create_mdl_shader(stage, "/World/Material", "/path/to/materials.mdl", "my_material")

Find Shader Overloads and Properties#

import omni.UsdMdl as UsdMdl
from pxr import Sdr

# Find all available overloads for a shader
def find_shader_overloads(prim, connected_only=False):
    overloads = UsdMdl.RegistryUtils.GetOverloads(prim, connected_only)
    
    print(f"Found {len(overloads)} overloads:")
    for sdr_node in overloads:
        print(f"  • {sdr_node.GetSubIdentifier()}")
        print(f"    Module: {sdr_node.GetModuleUsdIdentifier()}")
        print(f"    Name with signature: {sdr_node.GetNameWithSignature()}")
    
    return overloads

# Print detailed information about a shader node
def print_shader_node_info(sdr_node):
    print(f"Shader node: {sdr_node.GetName()}")
    print(f"Version: {sdr_node.GetVersion()}")
    print(f"Identifier: {sdr_node.GetIdentifier()}")
    print(f"Module UUID identifier: {sdr_node.GetModuleUsdIdentifier()}")
    print(f"Asset path: {sdr_node.GetAssetPath()}")
    
    # Print inputs
    print("\nInputs:")
    for name in sdr_node.GetInputNames():
        input_prop = sdr_node.GetInput(name)
        print(f"  • {name}: {input_prop.GetTypeAsSdfType()[0]}")
        print(f"    Default value: {input_prop.GetDefaultValue()}")
    
    # Print outputs
    print("\nOutputs:")
    for name in sdr_node.GetOutputNames():
        output_prop = sdr_node.GetOutput(name)
        print(f"  • {name}: {output_prop.GetTypeAsSdfType()[0]}")

Work with MDL Types and Metadata#

import omni.UsdMdl as UsdMdl
from pxr import UsdShade, Sdf

# Create a shader with different MDL type properties
def create_shader_with_mdl_types(stage, prim_path):
    # Create a shader prim
    prim = stage.DefinePrim(prim_path, "Shader")
    shader = UsdShade.Shader(prim)
    
    # Create color input with MDL metadata
    color_input = shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f)
    color_input.Set((0.8, 0.2, 0.2))
    color_input.SetMetadata("sdrMetadata", {
        "renderType": UsdMdl.Types.Color
    })
    
    # Create float input with uniform modifier
    roughness = shader.CreateInput("roughness", Sdf.ValueTypeNames.Float)
    roughness.Set(0.5)
    roughness.SetMetadata("sdrMetadata", {
        "renderType": UsdMdl.Types.Float,
        UsdMdl.Metadata.Modifier: UsdMdl.TypeModifiers.Uniform
    })
    
    # Create texture input with gamma metadata
    texture = shader.CreateInput("albedoTexture", Sdf.ValueTypeNames.Asset)
    texture.Set(Sdf.AssetPath("/textures/albedo.png"))
    texture.SetMetadata("sdrMetadata", {
        "renderType": UsdMdl.Types.Texture2d,
        "isAssetIdentifier": "1",
        UsdMdl.Metadata.TextureGamma: "2.2"
    })
    
    # Create struct input for material
    material = shader.CreateInput("material", Sdf.ValueTypeNames.Token)
    material.SetMetadata("sdrMetadata", {
        "renderType": UsdMdl.Types.Struct,
        UsdMdl.Metadata.StructType: UsdMdl.StructTypes.Material,
        UsdMdl.Metadata.Symbol: "::material"
    })
    
    return shader

# Print all available metadata tokens
metadata_tokens = UsdMdl.GetAllMetadataTokens()
print("Available MDL metadata tokens:", metadata_tokens)

Respond to MDL Module Load/Reload Events#

from pxr import Tf
import omni.UsdMdl as UsdMdl

# Function to handle module loaded notifications
def on_module_loaded(notice, sender):
    # Get the path of the loaded module
    resolved_path = notice.GetResolvedPath()
    print(f"MDL Module loaded: {resolved_path}")
    
    # You could perform actions like:
    # - Refresh UI showing available MDL materials
    # - Update material previews
    # - Log loading events

# Function to handle module reloaded notifications
def on_module_reloaded(notice, sender):
    resolved_path = notice.GetResolvedPath()
    print(f"MDL Module reloaded: {resolved_path}")
    
    # You could perform actions like:
    # - Update materials that use this module
    # - Refresh property UIs
    # - Notify users of updated modules

# Register notification listeners
load_listener = Tf.Notice.Register(UsdMdl.Notice.ModuleLoaded, on_module_loaded, None)
reload_listener = Tf.Notice.Register(UsdMdl.Notice.ModuleReloaded, on_module_reloaded, None)

# When no longer needed:
# load_listener = None  # This will unregister the listener
# reload_listener = None