26 template <
typename Renderer,
typename ShaderGen>
29 if (type ==
"color4" || type ==
"vector4")
33 if (type ==
"color3" || type ==
"vector3")
37 if (type ==
"vector2")
48 template <
typename Renderer,
typename ShaderGen>
50 Renderer(width, height, baseType),
51 _distanceUnit(
"meter"),
52 _averageImages(false),
53 _optimizeConstants(true),
54 _bakedGraphName(
"NG_baked"),
55 _bakedGeomInfoName(
"GI_baked"),
56 _textureFilenameTemplate(
"$MATERIAL_$SHADINGMODEL_$INPUT$UDIMPREFIX$UDIM.$EXTENSION"),
57 _outputStream(&std::cout),
58 _hashImageNames(false),
59 _textureSpaceMin(0.0
f),
60 _textureSpaceMax(1.0
f),
61 _generator(ShaderGen::create()),
62 _permittedOverrides({
"$ASSET",
"$MATERIAL",
"$UDIMPREFIX" }),
69 #if MATERIALX_BUILD_OIIO
78 #if MATERIALX_BUILD_OIIO
91 #if MATERIALX_BUILD_OIIO
97 _frameCaptureImage->createResourceBuffer();
100 template <
typename Renderer,
typename ShaderGen>
103 size_t i = filename.find(var, start);
104 if (var ==
"$UDIM" && i != string::npos)
106 size_t udimPrefix = filename.find(
"$UDIMPREFIX", start);
109 i = filename.find(var, i + 1);
115 template <
typename Renderer,
typename ShaderGen>
118 string bakedImageName = _textureFilenameTemplate;
120 for (
auto& pair : filenameTemplateMap)
122 string replacement = (_texTemplateOverrides.count(pair.first)) ? _texTemplateOverrides[pair.first] : pair.second;
123 replacement = (filenameTemplateMap.at(
"$UDIM").empty() && pair.first ==
"$UDIMPREFIX") ?
EMPTY_STRING : replacement;
125 for (
size_t i = 0; (i = findVarInTemplate(bakedImageName, pair.first, i)) != string::npos; i++)
127 bakedImageName.replace(i, pair.first.length(), replacement);
133 std::stringstream hashStream;
134 hashStream << std::hash<std::string>{}(bakedImageName);
135 hashStream <<
"." + getExtension();
136 bakedImageName = hashStream.str();
138 return _outputImagePath / bakedImageName;
141 template <
typename Renderer,
typename ShaderGen>
147 filenameTemplateMap[
"$ASSET"] = assetPath.
getBaseName();
148 filenameTemplateMap[
"$INPUT"] = _bakedInputMap[input->getName()];
149 filenameTemplateMap[
"$EXTENSION"] = _extension;
150 filenameTemplateMap[
"$MATERIAL"] = _material->getName();
151 filenameTemplateMap[
"$SHADINGMODEL"] = shader->getCategory();
152 filenameTemplateMap[
"$UDIM"] = udim;
154 return filenameTemplateMap;
157 template <
typename Renderer,
typename ShaderGen>
164 *_outputStream <<
"Failed to write baked image: " << baked.
filename.
asString() << std::endl;
171 *_outputStream <<
"Wrote baked image: " << baked.
filename.
asString() << std::endl;
177 template <
typename Renderer,
typename ShaderGen>
180 _material = material;
187 std::unordered_map<OutputPtr, InputPtr> bakedOutputMap;
188 for (
InputPtr input : shader->getInputs())
190 OutputPtr output = input->getConnectedOutput();
191 if (output && !bakedOutputMap.count(output))
193 bakedOutputMap[output] = input;
194 _bakedInputMap[input->getName()] = input->getName();
200 output->setConnectedNode(worldSpaceNode->getConnectedNode(
"in"));
201 _worldSpaceNodes[input->getName()] = worldSpaceNode;
203 StringMap filenameTemplateMap = initializeFileTemplateMap(input, shader, udim);
204 bakeGraphOutput(output, context, filenameTemplateMap);
206 else if (bakedOutputMap.count(output))
209 _bakedInputMap[input->getName()] = bakedOutputMap[output]->getName();
214 Renderer::_imageHandler->clearImageCache();
217 template <
typename Renderer,
typename ShaderGen>
225 bool encodeSrgb = _colorSpace ==
SRGB_TEXTURE && output->isColorType();
226 Renderer::getFramebuffer()->setEncodeSrgb(encodeSrgb);
228 ShaderPtr shader = _generator->generate(
"BakingShader", output, context);
229 Renderer::createProgram(shader);
232 Renderer::renderTextureSpace(getTextureSpaceMin(), getTextureSpaceMax());
233 string texturefilepath = generateTextureFilename(filenameTemplateMap);
234 Renderer::captureImage(_frameCaptureImage);
241 baked.
uniformColor = _frameCaptureImage->getAverageColor();
244 else if (_frameCaptureImage->isUniformColor(&baked.
uniformColor))
248 _bakedImageMap[output].push_back(baked);
254 writeBakedImage(baked, _frameCaptureImage);
258 template <
typename Renderer,
typename ShaderGen>
267 for (
auto& pair : _bakedImageMap)
269 bool outputIsUniform =
true;
274 outputIsUniform =
false;
281 bakedConstant.
color = pair.second[0].uniformColor;
282 _bakedConstantMap[pair.first] = bakedConstant;
287 NodeDefPtr shaderNodeDef = shader->getNodeDef();
290 for (
InputPtr shaderInput : shader->getInputs())
292 OutputPtr output = shaderInput->getConnectedOutput();
293 if (output && _bakedConstantMap.count(output))
295 InputPtr input = shaderNodeDef->getInput(shaderInput->getName());
298 Color4 uniformColor = _bakedConstantMap[output].color;
299 string uniformColorString = getValueStringFromColor(uniformColor, input->getType());
300 string defaultValueString = input->hasValue() ? input->
getValue()->getValueString() :
EMPTY_STRING;
301 if (uniformColorString == defaultValueString)
303 _bakedConstantMap[output].isDefault =
true;
311 for (
auto& pair : _bakedConstantMap)
313 if (pair.second.isDefault || _optimizeConstants || _averageImages)
315 _bakedImageMap.erase(pair.first);
320 template <
typename Renderer,
typename ShaderGen>
333 if (shader->getDocument()->hasColorSpace())
340 if (!_bakedImageMap.empty())
344 bakedNodeGraph->setColorSpace(_colorSpace);
346 _bakedGeomInfoName =
_bakedTextureDoc->createValidChildName(_bakedGeomInfoName);
359 string materialName = (_texTemplateOverrides.count(
"$MATERIAL")) ? _texTemplateOverrides[
"$MATERIAL"] : _material->getName();
360 NodePtr bakedMaterial =
_bakedTextureDoc->addNode(_material->getCategory(), materialName, _material->getType());
361 for (
auto sourceMaterialInput : _material->getInputs())
363 const string& sourceMaterialInputName = sourceMaterialInput->getName();
364 NodePtr upstreamShader = sourceMaterialInput->getConnectedNode();
365 if (upstreamShader && (upstreamShader->getNamePath() == shader->getNamePath()))
367 InputPtr bakedMaterialInput = bakedMaterial->getInput(sourceMaterialInputName);
368 if (!bakedMaterialInput)
370 bakedMaterialInput = bakedMaterial->addInput(sourceMaterialInputName, sourceMaterialInput->getType());
372 bakedMaterialInput->setNodeName(bakedShader->getName());
390 if (output && _bakedConstantMap.count(output) && _bakedConstantMap[output].isDefault)
396 const string& sourceName = sourceInput->getName();
397 const string& sourceType = sourceInput->getType();
398 InputPtr bakedInput = bakedShader->getInput(sourceName);
401 bakedInput = bakedShader->addInput(sourceName, sourceType);
408 if (_optimizeConstants && _bakedConstantMap.count(output))
410 Color4 uniformColor = _bakedConstantMap[output].color;
411 string uniformColorString = getValueStringFromColor(uniformColor, bakedInput->getType());
412 bakedInput->setValueString(uniformColorString);
413 if (bakedInput->isColorType())
415 bakedInput->setColorSpace(_colorSpace);
420 if (!_bakedImageMap.empty())
423 NodePtr bakedImage = bakedNodeGraph->addNode(
"image", sourceName, sourceType);
424 InputPtr input = bakedImage->addInput(
"file",
"filename");
426 input->setValueString(generateTextureFilename(filenameTemplateMap));
429 auto worldSpacePair = _worldSpaceNodes.find(sourceInput->getName());
430 if (worldSpacePair != _worldSpaceNodes.end())
432 NodePtr origWorldSpaceNode = worldSpacePair->second;
433 if (origWorldSpaceNode)
435 NodePtr newWorldSpaceNode = bakedNodeGraph->addNode(origWorldSpaceNode->getCategory(), sourceName +
"_map", sourceType);
436 newWorldSpaceNode->copyContentFrom(origWorldSpaceNode);
437 InputPtr mapInput = newWorldSpaceNode->getInput(
"in");
440 mapInput->setNodeName(bakedImage->getName());
442 bakedImage = newWorldSpaceNode;
447 OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName +
"_output", sourceType);
448 bakedOutput->setConnectedNode(bakedImage);
449 bakedInput->setConnectedOutput(bakedOutput);
454 bakedInput->copyContentFrom(sourceInput);
460 for (
const auto& pair : _bakedImageMap)
467 writeBakedImage(baked, uniformImage);
473 _bakedImageMap.clear();
474 _bakedConstantMap.clear();
475 _worldSpaceNodes.clear();
476 _bakedInputMap.clear();
483 template <
typename Renderer,
typename ShaderGen>
485 const StringVec& udimSet,
string& documentName)
489 *_outputStream <<
"Processing material: " << materialPath << std::endl;
499 cms->loadLibrary(doc);
505 if (materialTags.empty())
510 ElementPtr elem = doc->getDescendant(materialPath);
511 if (!elem || !elem->isA<
Node>())
518 NodePtr shaderNode = shaderNodes.empty() ?
nullptr : shaderNodes[0];
527 for (
const string& tag : materialTags)
537 Renderer::_imageHandler->setSearchPath(searchPath);
538 resolver->setUdimString(tag);
539 Renderer::_imageHandler->setFilenameResolver(resolver);
540 bakeShaderInputs(materialNode, shaderNode, genContext, tag);
543 optimizeBakedTextures(shaderNode);
547 documentName = shaderNode->getName();
548 return generateNewDocumentFromShader(shaderNode, udimSet);
551 template <
typename Renderer,
typename ShaderGen>
554 if (_outputImagePath.isEmpty())
557 if (!_outputImagePath.exists())
568 if (udimSetValue && udimSetValue->isA<
StringVec>())
570 udimSet = udimSetValue->asA<
StringVec>();
575 for (
size_t i = 0; i < renderableMaterials.size(); i++)
577 if (_outputStream && i > 0)
579 *_outputStream << std::endl;
584 DocumentPtr bakedMaterialDoc = bakeMaterialToDoc(doc, searchPath, element->getNamePath(), udimSet, documentName);
587 bakedDocuments.push_back(make_pair(documentName, bakedMaterialDoc));
594 size_t bakeCount = bakedDocuments.size();
595 for (
size_t i = 0; i < bakeCount; i++)
597 if (bakedDocuments[i].second)
599 FilePath writeFilename = outputFilename;
602 if (bakedDocuments.size() > 1)
613 *_outputStream <<
"Wrote baked document: " << writeFilename.
asString() << std::endl;
623 *_outputStream <<
"Wrote baked document: " << outputFilename.
asString() << std::endl;
628 template <
typename Renderer,
typename ShaderGen>
631 UnitTypeDefPtr distanceTypeDef = unitDefinitions ? unitDefinitions->getUnitTypeDef(
"distance") :
nullptr;
632 UnitTypeDefPtr angleTypeDef = unitDefinitions ? unitDefinitions->getUnitTypeDef(
"angle") :
nullptr;
633 if (!distanceTypeDef && !angleTypeDef)
643 _generator->setUnitSystem(unitSystem);
647 _generator->getUnitSystem()->loadLibrary(unitDefinitions);
648 _generator->getUnitSystem()->setUnitConverterRegistry(registry);
shared_ptr< Output > OutputPtr
A shared pointer to an Output.
const string DEFAULT_UDIM_PREFIX
GT_API const UT_StringHolder filename
static const string EXR_EXTENSION
const string SHADER_PREFIX
IMATH_HOSTDEVICE void getValue(S &a, S &b, S &c, S &d) const IMATH_NOEXCEPT
Return the value.
_writeDocumentPerMaterial(true)
void setColorManagementSystem(ColorManagementSystemPtr colorManagementSystem)
Sets the color management system.
#define MATERIALX_NAMESPACE_BEGIN
vector< string > StringVec
A vector of strings.
bool fileTextureVerticalFlip
MX_FORMAT_API void writeToXmlFile(DocumentPtr doc, const FilePath &filename, const XmlWriteOptions *writeOptions=nullptr)
void clearNodeImplementations()
Clear all cached shader node implementation.
shared_ptr< TypedElement > TypedElementPtr
A shared pointer to a TypedElement.
shared_ptr< class UnitSystem > UnitSystemPtr
A shared pointer to a UnitSystem.
MATERIALX_NAMESPACE_BEGIN MX_CORE_API const string EMPTY_STRING
static StringResolverPtr create()
Create a new string resolver.
const string SRGB_TEXTURE
static UnitConverterRegistryPtr create()
Creator.
GLenum GLenum GLsizei void * image
const string & getBaseName() const
static const string TIFF_EXTENSION
shared_ptr< GeomInfo > GeomInfoPtr
A shared pointer to a GeomInfo.
string targetColorSpaceOverride
bool writeBakedImage(const BakedImage &baked, ImagePtr image)
std::vector< std::pair< std::string, DocumentPtr >> BakedDocumentVec
A vector of baked documents with their associated names.
MX_GENSHADER_API vector< TypedElementPtr > findRenderableElements(ConstDocumentPtr doc)
bool isDirectory() const
Return true if the given path is a directory on the file system.
void createDirectory() const
Create a directory on the file system at the given path.
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER IMFUTIL_EXPORT void saveImage(const std::string &fileName, const Header &hdr, const Image &img, DataWindowSource dws=USE_IMAGE_DATA_WINDOW)
shared_ptr< UnitTypeDef > UnitTypeDefPtr
A shared pointer to a UnitTypeDef.
ShaderGenerator & getShaderGenerator()
Return shader generatior.
string getValueStringFromColor(const Color4 &color, const string &type)
StringMap initializeFileTemplateMap(InputPtr input, NodePtr shader, const string &udim=EMPTY_STRING)
void bakeAllMaterials(DocumentPtr doc, const FileSearchPath &searchPath, const FilePath &outputFileName)
GLint GLsizei GLsizei height
static const string PNG_EXTENSION
void removeExtension()
Remove the file extension, if any, from the given path.
virtual OutputPtr getConnectedOutput() const
Return the output, if any, to which this input is connected.
MATERIALX_NAMESPACE_BEGIN MX_CORE_API vector< NodePtr > getShaderNodes(NodePtr materialNode, const string &nodeType=SURFACE_SHADER_TYPE_STRING, const string &target=EMPTY_STRING)
static LinearUnitConverterPtr create(UnitTypeDefPtr UnitDef)
Creator.
void bakeGraphOutput(OutputPtr output, GenContext &context, const StringMap &filenameTemplateMap)
Bake a texture for the given graph output.
TextureBaker(unsigned int width, unsigned int height, Image::BaseType baseType, bool flipSavedImage)
static ImagePtr create(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType=BaseType::UINT8)
Create an empty image with the given properties.
static DefaultColorManagementSystemPtr create(const string &target)
Create a new DefaultColorManagementSystem.
shared_ptr< Document > DocumentPtr
A shared pointer to a Document.
string getExtension() const
Return the file extension of the given path.
MX_RENDER_API ImagePtr createUniformImage(unsigned int width, unsigned int height, unsigned int channelCount, Image::BaseType baseType, const Color4 &color)
Create a uniform-color image with the given properties.
void optimizeBakedTextures(NodePtr shader)
Optimize baked textures before writing.
DocumentPtr bakeMaterialToDoc(DocumentPtr doc, const FileSearchPath &searchPath, const string &materialPath, const StringVec &udimSet, std::string &documentName)
Bake material to document in memory and write baked textures to disk.
OPENVDB_API void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
_flipSavedImage(flipSavedImage)
shared_ptr< Input > InputPtr
A shared pointer to an Input.
size_t findVarInTemplate(const string &filename, const string &var, size_t start=0)
virtual const string & getTarget() const
Return the name of the target this generator is for.
string asString(Format format=FormatNative) const
Return this path as a standard string with the given format.
shared_ptr< StringResolver > StringResolverPtr
A shared pointer to a StringResolver.
shared_ptr< UnitConverterRegistry > UnitConverterRegistryPtr
A shared pointer to a UnitConverterRegistry.
FilePath generateTextureFilename(const StringMap &fileTemplateMap)
MX_GENSHADER_API NodePtr connectsToWorldSpaceNode(OutputPtr output)
GenOptions & getOptions()
Return shader generation options.
static UnitSystemPtr create(const string &target)
Create a new UnitSystem.
DocumentPtr generateNewDocumentFromShader(NodePtr shader, const StringVec &udimSet)
std::unordered_map< string, string > StringMap
An unordered map with strings as both keys and values.
MX_RENDER_API ShaderPtr createShader(const string &shaderName, GenContext &context, ElementPtr elem)
Create a shader for a given element.
shared_ptr< Shader > ShaderPtr
Shared pointer to a Shader.
void bakeShaderInputs(NodePtr material, NodePtr shader, GenContext &context, const string &udim=EMPTY_STRING)
Bake textures for all graph inputs of the given shader.
shared_ptr< Element > ElementPtr
A shared pointer to an Element.
shared_ptr< ValueElement > ValueElementPtr
A shared pointer to a ValueElement.
#define MATERIALX_NAMESPACE_END
string targetDistanceUnit
static OiioImageLoaderPtr create()
Create a new OpenImageIO image loader.
shared_ptr< Image > ImagePtr
A shared pointer to an image.
static const string HDR_EXTENSION
FilePath getParentPath() const
MX_CORE_API const string UDIM_TOKEN
shared_ptr< Value > ValuePtr
A shared pointer to a Value.
shared_ptr< NodeGraph > NodeGraphPtr
A shared pointer to a NodeGraph.
MX_CORE_API const string UDIM_SET_PROPERTY
void setupUnitSystem(DocumentPtr unitDefinitions)
Set up the unit definitions to be used in baking.
MX_CORE_API string toValueString(const T &data)
Convert the given data value to a value string.
OIIO_UTIL_API std::string extension(string_view filepath, bool include_dot=true) noexcept
shared_ptr< class DefaultColorManagementSystem > DefaultColorManagementSystemPtr
A shared pointer to a DefaultColorManagementSystem.
static StbImageLoaderPtr create()
Create a new stb image loader.
shared_ptr< Node > NodePtr
A shared pointer to a Node.
void registerSourceCodeSearchPath(const FilePath &path)
shared_ptr< NodeDef > NodeDefPtr
A shared pointer to a NodeDef.
_bakedTextureDoc(nullptr)