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)) ?
123 _texTemplateOverrides[pair.first] : pair.second;
124 replacement = (filenameTemplateMap.at(
"$UDIM").empty() && pair.first ==
"$UDIMPREFIX") ?
127 for (
size_t i = 0; (i = findVarInTemplate(bakedImageName, pair.first, i)) != string::npos; i++)
129 bakedImageName.replace(i, pair.first.length(), replacement);
135 std::stringstream hashStream;
136 hashStream << std::hash<std::string>{}(bakedImageName);
137 hashStream <<
"." + getExtension();
138 bakedImageName = hashStream.str();
140 return _outputImagePath / bakedImageName;
143 template<
typename Renderer,
typename ShaderGen>
149 filenameTemplateMap[
"$ASSET"] = assetPath.
getBaseName();
150 filenameTemplateMap[
"$INPUT"] = _bakedInputMap[input->getName()];
151 filenameTemplateMap[
"$EXTENSION"] = _extension;
152 filenameTemplateMap[
"$MATERIAL"] = _material->getName();
153 filenameTemplateMap[
"$SHADINGMODEL"] = shader->getCategory();
154 filenameTemplateMap[
"$UDIM"] = udim;
156 return filenameTemplateMap;
159 template<
typename Renderer,
typename ShaderGen>
166 *_outputStream <<
"Failed to write baked image: " << baked.
filename.
asString() << std::endl;
173 *_outputStream <<
"Wrote baked image: " << baked.
filename.
asString() << std::endl;
179 template<
typename Renderer,
typename ShaderGen>
182 _material = material;
189 std::unordered_map<OutputPtr, InputPtr> bakedOutputMap;
190 for (
InputPtr input : shader->getInputs())
192 OutputPtr output = input->getConnectedOutput();
193 if (output && !bakedOutputMap.count(output))
195 bakedOutputMap[output] = input;
196 _bakedInputMap[input->getName()] = input->getName();
202 output->setConnectedNode(worldSpaceNode->getConnectedNode(
"in"));
203 _worldSpaceNodes[input->getName()] = worldSpaceNode;
205 StringMap filenameTemplateMap = initializeFileTemplateMap(input, shader, udim);
206 bakeGraphOutput(output, context, filenameTemplateMap);
208 else if (bakedOutputMap.count(output))
211 _bakedInputMap[input->getName()] = bakedOutputMap[output]->getName();
216 Renderer::_imageHandler->clearImageCache();
219 template<
typename Renderer,
typename ShaderGen>
228 (output->getType() ==
"color3" || output->getType() ==
"color4");
229 Renderer::getFramebuffer()->setEncodeSrgb(encodeSrgb);
231 ShaderPtr shader = _generator->generate(
"BakingShader", output, context);
232 Renderer::createProgram(shader);
235 Renderer::renderTextureSpace(getTextureSpaceMin(), getTextureSpaceMax());
236 string texturefilepath = generateTextureFilename(filenameTemplateMap);
237 Renderer::captureImage(_frameCaptureImage);
244 baked.
uniformColor = _frameCaptureImage->getAverageColor();
247 else if (_frameCaptureImage->isUniformColor(&baked.
uniformColor))
251 _bakedImageMap[output].push_back(baked);
257 writeBakedImage(baked, _frameCaptureImage);
261 template<
typename Renderer,
typename ShaderGen>
270 for (
auto& pair : _bakedImageMap)
272 bool outputIsUniform =
true;
277 outputIsUniform =
false;
284 bakedConstant.
color = pair.second[0].uniformColor;
285 _bakedConstantMap[pair.first] = bakedConstant;
290 NodeDefPtr shaderNodeDef = shader->getNodeDef();
293 for (
InputPtr shaderInput : shader->getInputs())
295 OutputPtr output = shaderInput->getConnectedOutput();
296 if (output && _bakedConstantMap.count(output))
298 InputPtr input = shaderNodeDef->getInput(shaderInput->getName());
301 Color4 uniformColor = _bakedConstantMap[output].color;
302 string uniformColorString = getValueStringFromColor(uniformColor, input->getType());
303 string defaultValueString = input->hasValue() ? input->
getValue()->getValueString() :
EMPTY_STRING;
304 if (uniformColorString == defaultValueString)
306 _bakedConstantMap[output].isDefault =
true;
314 for (
auto& pair : _bakedConstantMap)
316 if (pair.second.isDefault || _optimizeConstants || _averageImages)
318 _bakedImageMap.erase(pair.first);
323 template<
typename Renderer,
typename ShaderGen>
336 if (shader->getDocument()->hasColorSpace())
343 if (!_bakedImageMap.empty())
347 bakedNodeGraph->setColorSpace(_colorSpace);
349 _bakedGeomInfoName =
_bakedTextureDoc->createValidChildName(_bakedGeomInfoName);
362 string materialName = (_texTemplateOverrides.count(
"$MATERIAL"))? _texTemplateOverrides[
"$MATERIAL"] : _material->getName();
364 for (
auto sourceMaterialInput : _material->getInputs())
366 const string& sourceMaterialInputName = sourceMaterialInput->getName();
367 NodePtr upstreamShader = sourceMaterialInput->getConnectedNode();
368 if (upstreamShader && (upstreamShader->getNamePath() == shader->getNamePath()))
370 InputPtr bakedMaterialInput = bakedMaterial->getInput(sourceMaterialInputName);
371 if (!bakedMaterialInput)
373 bakedMaterialInput = bakedMaterial->addInput(sourceMaterialInputName, sourceMaterialInput->getType());
375 bakedMaterialInput->setNodeName(bakedShader->getName());
393 if (output && _bakedConstantMap.count(output) && _bakedConstantMap[output].isDefault)
399 const string& sourceName = sourceInput->getName();
400 const string& sourceType = sourceInput->getType();
401 InputPtr bakedInput = bakedShader->getInput(sourceName);
404 bakedInput = bakedShader->addInput(sourceName, sourceType);
411 if (_optimizeConstants && _bakedConstantMap.count(output))
413 Color4 uniformColor = _bakedConstantMap[output].color;
414 string uniformColorString = getValueStringFromColor(uniformColor, bakedInput->getType());
415 bakedInput->setValueString(uniformColorString);
416 if (bakedInput->getType() ==
"color3" || bakedInput->getType() ==
"color4")
418 bakedInput->setColorSpace(_colorSpace);
423 if (!_bakedImageMap.empty())
427 InputPtr input = bakedImage->addInput(
"file",
"filename");
429 input->setValueString(generateTextureFilename(filenameTemplateMap));
432 auto worldSpacePair = _worldSpaceNodes.find(sourceInput->getName());
433 if (worldSpacePair != _worldSpaceNodes.end())
435 NodePtr origWorldSpaceNode = worldSpacePair->second;
436 if (origWorldSpaceNode)
438 NodePtr newWorldSpaceNode = bakedNodeGraph->addNode(origWorldSpaceNode->getCategory(), sourceName +
BAKED_POSTFIX +
"_map", sourceType);
439 newWorldSpaceNode->copyContentFrom(origWorldSpaceNode);
440 InputPtr mapInput = newWorldSpaceNode->getInput(
"in");
443 mapInput->setNodeName(bakedImage->getName());
445 bakedImage = newWorldSpaceNode;
450 OutputPtr bakedOutput = bakedNodeGraph->addOutput(sourceName +
"_output", sourceType);
451 bakedOutput->setConnectedNode(bakedImage);
452 bakedInput->setConnectedOutput(bakedOutput);
457 bakedInput->copyContentFrom(sourceInput);
463 for (
const auto& pair : _bakedImageMap)
470 writeBakedImage(baked, uniformImage);
476 _bakedImageMap.clear();
477 _bakedConstantMap.clear();
478 _worldSpaceNodes.clear();
479 _bakedInputMap.clear();
486 template<
typename Renderer,
typename ShaderGen>
488 const StringVec& udimSet,
string& documentName)
492 *_outputStream <<
"Processing material: " << materialPath << std::endl;
502 cms->loadLibrary(doc);
508 if (materialTags.empty())
513 ElementPtr elem = doc->getDescendant(materialPath);
514 if (!elem || !elem->isA<
Node>())
521 NodePtr shaderNode = shaderNodes.empty() ?
nullptr : shaderNodes[0];
530 for (
const string& tag : materialTags)
540 Renderer::_imageHandler->setSearchPath(searchPath);
541 resolver->setUdimString(tag);
542 Renderer::_imageHandler->setFilenameResolver(resolver);
543 bakeShaderInputs(materialNode, shaderNode, genContext, tag);
546 optimizeBakedTextures(shaderNode);
550 documentName = shaderNode->getName();
551 return generateNewDocumentFromShader(shaderNode, udimSet);
554 template<
typename Renderer,
typename ShaderGen>
557 if (_outputImagePath.isEmpty())
560 if (!_outputImagePath.exists())
571 if (udimSetValue && udimSetValue->isA<
StringVec>())
573 udimSet = udimSetValue->asA<
StringVec>();
578 for (
size_t i = 0; i < renderableMaterials.size(); i++)
580 if (_outputStream && i > 0)
582 *_outputStream << std::endl;
587 DocumentPtr bakedMaterialDoc = bakeMaterialToDoc(doc, searchPath, element->getNamePath(), udimSet, documentName);
590 bakedDocuments.push_back(make_pair(documentName, bakedMaterialDoc));
597 size_t bakeCount = bakedDocuments.size();
598 for (
size_t i = 0; i < bakeCount; i++)
600 if (bakedDocuments[i].second)
602 FilePath writeFilename = outputFilename;
605 if (bakedDocuments.size() > 1)
616 *_outputStream <<
"Wrote baked document: " << writeFilename.
asString() << std::endl;
626 *_outputStream <<
"Wrote baked document: " << outputFilename.
asString() << std::endl;
631 template<
typename Renderer,
typename ShaderGen>
634 UnitTypeDefPtr distanceTypeDef = unitDefinitions ? unitDefinitions->getUnitTypeDef(
"distance") :
nullptr;
635 UnitTypeDefPtr angleTypeDef = unitDefinitions ? unitDefinitions->getUnitTypeDef(
"angle") :
nullptr;
636 if (!distanceTypeDef && !angleTypeDef)
646 _generator->setUnitSystem(unitSystem);
650 _generator->getUnitSystem()->loadLibrary(unitDefinitions);
651 _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.
const string BAKED_POSTFIX
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)