28 Command to parse PhysicallyBased materials and create MaterialX materials
30 logger = logging.getLogger(
'PB_CMD')
31 logging.basicConfig(level=logging.INFO)
33 parser = argparse.ArgumentParser(description=
'Convert Physically Based Materials to MaterialX')
34 parser.add_argument(
'-m',
'--shadingModel', type=str, default=
'', help=
'Shading models to use for conversion. '
35 ' If not specified then all will be used. '
36 ' Options: standard_surface, gltf_pbr, open_pbr_surface')
37 parser.add_argument(
'-o',
'--outputDir', type=str, default=
'',
38 help=
'Output directory for MaterialX files. Default location is PhysicallyBasedMaterialX')
39 parser.add_argument(
'-j',
'--writeJSON', type=bool, default=
True,
40 help=
'Write materials JSON file. Default is True')
41 parser.add_argument(
'-s',
'--separateFiles', type=bool, default=
False,
42 help=
'Convert individual MaterialX files per material. Default is false')
43 parser.add_argument(
'-l',
'--loadFromFile', type=str, default=
'', help=
'Load materials a specified file')
44 parser.add_argument(
'-wr',
'--writeRemapping', type=bool, default=
False, help=
'Write remapping from PhysicallyBased to MaterialX. Default is False')
45 parser.add_argument(
'-rr',
'--readRemapping', type=str, default=
'', help=
'Read remapping from PhysicallyBased to MaterialX. Default is empty')
46 parser.add_argument(
'-nd',
'--createNodeDef', type=bool, default=
False, help=
'Create NodeDef for Physically Based Material inputs. Default is False')
49 support_colorspaces =
False
50 if support_colorspaces:
51 parser.add_argument(
'-cs',
'--colorspace', type=str, default=
'', help=
'Write colors using this color space. Default is to use srgb-linear = lin_rec709. Options incllude: srgb-linear, acescg')
53 opts = parser.parse_args()
55 outputDir =
'PhysicallyBasedMaterialX'
57 if not os.path.exists(opts.outputDir):
58 logger.info(f
'Error: Output directory does not exist: {opts.outputDir}')
61 os.makedirs(opts.outputDir)
62 logger.info(f
'> Created output directory: {opts.outputDir}')
63 outputDir = opts.outputDir
64 except Exception
as e:
65 logger.info(f
'> Error: Could not create output directory: {opts.outputDir}')
68 outputDir = opts.outputDir
72 shadingModels = opts.shadingModel.split(
',')
73 shadingModePrefixMap = {
'standard_surface':
'SS',
'gltf_pbr':
'GLTF',
'open_pbr_surface':
'OPBR' }
74 shadingModelPrefixes = []
75 if len(shadingModels) == 0:
76 shadingModels = [
'standard_surface',
'gltf_pbr',
'open_pbr_surface']
77 shadingModelPrefixes = [
'SS',
'GLTF',
'OPBR']
79 for shadingModel
in shadingModels:
80 shadingModelPrefixes.append(shadingModePrefixMap[shadingModel])
82 writeJSON = opts.writeJSON
83 separateFiles = opts.separateFiles
85 material_file = opts.loadFromFile
87 if not os.path.exists(opts.loadFromFile):
88 logger.info(f
'> Error: File does not exist: {material_file}')
90 logger.info(f
'> Load materials from file: {material_file}')
94 loader = pbmx.PhysicallyBasedMaterialLoader(mx,
None, material_file)
95 if support_colorspaces
and opts.colorspace:
96 loader.set_desired_color_space(opts.colorspace)
98 readRemapping = opts.readRemapping
100 if not os.path.exists(readRemapping):
101 logger.info(f
'> Error: Remapping file does not exist: {readRemapping}')
102 logger.info(f
'> Read remapping file: {readRemapping}')
103 loader.readRemappingFile(readRemapping)
105 writeRemapping = opts.writeRemapping
107 outputFile = os.path.join(outputDir,
'PhysicallyBasedToMtlxMappings.json')
108 logger.info(f
'> Write remapping file: {outputFile}')
109 loader.writeRemappingFile(outputFile)
111 jsonMat = loader.getJSON()
115 os.makedirs(outputDir, exist_ok=
True)
117 create_nodedef = opts.createNodeDef
122 logger.info(
'> Write definition for PhysicallyBased materials')
123 definitions_doc = loader.get_physlib()
125 nodedef_file_name = os.path.join(outputDir,
'physbased_pbr.mtlx')
126 mx.writeToXmlFile(definitions_doc, nodedef_file_name)
127 logger.info(f
'> Write definition file: {nodedef_file_name}')
131 doc_mat = loader.get_physlib_materials()
133 status, error = doc_mat.validate()
135 logger.error(
'> Error validating definition materials document:')
138 logger.info(
'> Definition materials document passed validation.')
140 nodedef_mat_file_name = os.path.join(outputDir,
'physbased_pbr_materials.mtlx')
141 mx.writeToXmlFile(doc_mat, mx.FilePath(nodedef_mat_file_name))
142 logger.info(f
'> Write materials file: {nodedef_mat_file_name}')
146 translators_doc = loader.get_translators()
147 translators = translators_doc.getNodeDefs()
148 print(f
'Found translator definitions: {len(translators)}')
150 if translators_doc
and translators:
151 output_file_name =
'physbased_pbr_translators.mtlx'
152 output_path = os.path.join(outputDir, output_file_name)
153 logger.info(
'> Write translator file:' + output_path)
154 mx.writeToXmlFile(translators_doc, mx.FilePath(output_path))
155 logger.info(f
'> Write translator file: {output_path}')
158 stdlib = loader.get_definitions()
161 if not separateFiles:
162 translated_doc = loader.get_physlib_materials()
168 for shadingModel, prefix
in zip(shadingModels, shadingModelPrefixes):
170 for node
in translated_doc.getNodes():
171 if node.getCategory() == loader.get_physlib_category():
172 trans_result = loader.translate_node(translated_doc, loader.get_physlib_category(), shadingModel, node)
174 logger.info(f
'> Generate MaterialX using nodedefs for shading model: {shadingModel}')
175 fileName = os.path.join(outputDir, f
'PhysicallyBasedMaterialX_translated_{prefix}.mtlx')
176 loader.writeMaterialXToFile(fileName, translated_doc)
177 logger.info(f
'> Write: {fileName}')
181 matDir = os.path.join(outputDir,
'Sep')
182 os.makedirs(matDir, exist_ok=
True)
183 for shadingModel, prefix
in zip(shadingModels, shadingModelPrefixes):
185 for mat
in loader.getJSONMaterialNames():
186 materialFilter = [mat]
189 matdoc = loader.create_definition_materials(
None, materialFilter)
190 if matdoc
is not None:
193 mat_name = mx.createValidName(mat)
194 node = matdoc.getNode(mat_name)
196 trans_result = loader.translate_node(matdoc, loader.get_physlib_category(), shadingModel, node)
198 logger.warning(f
'Failed to translate node: {mat_name} for shading model: {shadingModel}')
200 converted.append(trans_result[
'targetNode'].getName())
201 valid, errors = loader.validateMaterialXDocument(matdoc)
204 fileName = os.path.join(matDir, f
'PB_{prefix}_{mat}.mtlx')
205 loader.writeMaterialXToFile(fileName, matdoc)
206 logger.info(f
'> Write: {fileName}')
208 logger.info(f
'> Converted {len(converted)} materials for shading model: {shadingModel}')
211 logger.info(f
'> Write PB material file: {outputDir}/PhysicallyBasedMaterial.json')
212 loader.writeJSONToFile(os.path.join(outputDir,
'PhysicallyBasedMaterial.json'))
218 if not separateFiles:
219 for shadingModel, prefix
in zip(shadingModels, shadingModelPrefixes):
220 logger.info(f
'> Generate MaterialX for shading model: {shadingModel}')
221 matdoc = loader.convertToMaterialX([], shadingModel, {}, prefix)
222 valid, errors = loader.validateMaterialXDocument(matdoc)
224 logger.error(f
'> Error validating MaterialX document for shading model: {shadingModel}')
227 if support_colorspaces
and opts.colorspace:
228 prefix = prefix +
'_' + opts.colorspace
229 fileName = os.path.join(outputDir, f
'PhysicallyBasedMaterialX_{prefix}.mtlx')
230 loader.writeMaterialXToFile(fileName)
231 logger.info(f
'> Write: {fileName}')
234 for shadingModel, prefix
in zip(shadingModels, shadingModelPrefixes):
235 logger.info(f
'> Generate MaterialX for shading model: {shadingModel}')
236 for mat
in loader.getJSONMaterialNames():
237 materialFilter = [mat]
238 matdoc = loader.convertToMaterialX(materialFilter, shadingModel, {}, prefix)
239 if matdoc
is not None:
240 valid, errors = loader.validateMaterialXDocument(matdoc)
242 logger.error(f
'> Error validating MaterialX document for material: {mat} shading model: {shadingModel}')
245 if support_colorspaces
and opts.colorspace:
246 prefix = prefix +
'_' + opts.colorspace
247 fileName = os.path.join(outputDir, f
'PB_{prefix}_{mat}.mtlx')
248 loader.writeMaterialXToFile(fileName)
249 logger.info(f
'> Write: {fileName}')
252 logger.info(
'Could not retrieve PhysicallyBased Materials')