My USD file textures are exporting from max without textures. For some reason the way max exports them, they don’t appear on my models in Unreal. I’m also exporting them from unreal with the meta data.
This image is before I made my edits to the USD in 3ds max, note the folder structure and materials, they work great, usd re-imports to unreal and looks fine.
After export max butchers the layout and now my materials are black in Unreal when I re-import the USD. Note the weird nodes max creates. I don’t know how to fix this.
Awesome Autodesk guy working on USD importer/exporter for max wrote this chaser script to fix the problem on export. Here is the script to run in max before export which fixes the problem. Make sure to check the fix unreal texture option in the export dialog:
import maxUsd
from pxr import Usd
from pymxs import runtime as mxs
import os, sys, glob
class matFixChaser(maxUsd.ExportChaser):
def __init__(self, factoryContext, *args, **kwargs):
super(matFixChaser, self).__init__(factoryContext, *args, **kwargs)
self.stage = factoryContext.GetStage()
def isId(self, id , shader):
info_id_attr = shader.GetIdAttr()
if info_id_attr:
id_value = info_id_attr.Get()
return id_value == id
return False
def PostExport(self):
try:
print("Running Unreal UsdPreviewSurface fix chaser...")
all_shaders = [x for x in self.stage.Traverse() if UsdShade.Shader(x)]
for prim in all_shaders:
shader = UsdShade.Shader(prim)
if self.isId('UsdPreviewSurface', shader):
# Iterate over the shader's inputs
for input in shader.GetInputs():
# Check if the input is connected
if input.HasConnectedSource():
# Get the connected path
source = input.GetConnectedSource()
source_prim = source[0].GetPrim()
# The node graph connection...
connection_path = source_prim.GetPath()
# print(connection_path)
# Instead connect to the USD texture 2d that lives inside the node graph.
new_connection = connection_path.AppendChild(source_prim.GetName())
# print(new_connection)
texture = UsdShade.Shader(self.stage.GetPrimAtPath(new_connection))
input.ConnectToSource(texture.ConnectableAPI(), 'rgb')
continue
if self.isId('UsdPrimvarReader_float2', shader):
varname_input = shader.GetInput("varname")
varname_value_attributes = varname_input.GetValueProducingAttributes()
primvar_name = varname_value_attributes[0].Get()
# Punch in value directly, not from nodegraph...
varname_input.Set(primvar_name)
except Exception as e:
print('Chaser ERROR : %s' % str(e))
print(traceback.format_exc())
return True
maxUsd.ExportChaser.Register(matFixChaser, "unrealMatFixer", "Unreal UsdPreviewSurface fix chaser", "Connects straight to textures, bypassing nodegraphs.")
def unrealMatFixContext():
extraArgs = {}
extraArgs['chaser'] = ['unrealMatFixer']
extraArgs['chaserNames'] = ['unrealMatFixer']
return extraArgs
registeredContexts = maxUsd.JobContextRegistry.ListJobContexts()
if 'unrealMatFixContext' not in registeredContexts:
maxUsd.JobContextRegistry.RegisterExportJobContext("unrealMatFixContext", "Fix USD Preview Surface for Unreal", "Fixes USD preview surface materials for usage in Unreal, avoiding NodeGraphs.", unrealMatFixContext)
print("Registered unreal material fixer")