310 lines
9.3 KiB
C++
310 lines
9.3 KiB
C++
//
|
|
// Copyright Contributors to the MaterialX Project
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
#ifndef MATERIALX_TEXTUREBAKER
|
|
#define MATERIALX_TEXTUREBAKER
|
|
|
|
/// @file
|
|
/// Texture baking functionality
|
|
|
|
#include <iostream>
|
|
|
|
#include <MaterialXCore/Unit.h>
|
|
|
|
#include <MaterialXRender/Export.h>
|
|
#include <MaterialXFormat/File.h>
|
|
#include <MaterialXRender/ImageHandler.h>
|
|
#include <MaterialXGenShader/GenContext.h>
|
|
|
|
MATERIALX_NAMESPACE_BEGIN
|
|
|
|
/// A vector of baked documents with their associated names.
|
|
using BakedDocumentVec = std::vector<std::pair<std::string, DocumentPtr>>;
|
|
|
|
/// @class TextureBaker
|
|
/// A helper class for baking procedural material content to textures.
|
|
/// TODO: Add support for graphs containing geometric nodes such as position
|
|
/// and normal.
|
|
template <typename Renderer, typename ShaderGen>
|
|
class TextureBaker : public Renderer
|
|
{
|
|
public:
|
|
/// Set the file extension for baked textures.
|
|
void setExtension(const string& extension)
|
|
{
|
|
_extension = extension;
|
|
}
|
|
|
|
/// Return the file extension for baked textures.
|
|
const string& getExtension() const
|
|
{
|
|
return _extension;
|
|
}
|
|
|
|
/// Set the color space in which color textures are encoded.
|
|
///
|
|
/// By default, this color space is srgb_texture, and color inputs are
|
|
/// automatically transformed to this space by the baker. If another color
|
|
/// space is set, then the input graph is responsible for transforming
|
|
/// colors to this space.
|
|
void setColorSpace(const string& colorSpace)
|
|
{
|
|
_colorSpace = colorSpace;
|
|
}
|
|
|
|
/// Return the color space in which color textures are encoded.
|
|
const string& getColorSpace() const
|
|
{
|
|
return _colorSpace;
|
|
}
|
|
|
|
/// Set the distance unit to which textures are baked. Defaults to meters.
|
|
void setDistanceUnit(const string& unitSpace)
|
|
{
|
|
_distanceUnit = unitSpace;
|
|
}
|
|
|
|
/// Return the distance unit to which textures are baked.
|
|
const string& getDistanceUnit() const
|
|
{
|
|
return _distanceUnit;
|
|
}
|
|
|
|
/// Set whether images should be averaged to generate constants. Defaults to false.
|
|
void setAverageImages(bool enable)
|
|
{
|
|
_averageImages = enable;
|
|
}
|
|
|
|
/// Return whether images should be averaged to generate constants.
|
|
bool getAverageImages() const
|
|
{
|
|
return _averageImages;
|
|
}
|
|
|
|
/// Set whether uniform textures should be stored as constants. Defaults to true.
|
|
void setOptimizeConstants(bool enable)
|
|
{
|
|
_optimizeConstants = enable;
|
|
}
|
|
|
|
/// Return whether uniform textures should be stored as constants.
|
|
bool getOptimizeConstants() const
|
|
{
|
|
return _optimizeConstants;
|
|
}
|
|
|
|
/// Set the output location for baked texture images. Defaults to the root folder
|
|
/// of the destination material.
|
|
void setOutputImagePath(const FilePath& outputImagePath)
|
|
{
|
|
_outputImagePath = outputImagePath;
|
|
}
|
|
|
|
/// Get the current output location for baked texture images.
|
|
const FilePath& getOutputImagePath()
|
|
{
|
|
return _outputImagePath;
|
|
}
|
|
|
|
/// Set the name of the baked graph element.
|
|
void setBakedGraphName(const string& name)
|
|
{
|
|
_bakedGraphName = name;
|
|
}
|
|
|
|
/// Return the name of the baked graph element.
|
|
const string& getBakedGraphName() const
|
|
{
|
|
return _bakedGraphName;
|
|
}
|
|
|
|
/// Set the name of the baked geometry info element.
|
|
void setBakedGeomInfoName(const string& name)
|
|
{
|
|
_bakedGeomInfoName = name;
|
|
}
|
|
|
|
/// Return the name of the baked geometry info element.
|
|
const string& getBakedGeomInfoName() const
|
|
{
|
|
return _bakedGeomInfoName;
|
|
}
|
|
|
|
/// Get the texture filename template.
|
|
const string& getTextureFilenameTemplate() const
|
|
{
|
|
return _textureFilenameTemplate;
|
|
}
|
|
|
|
/// Set the texture filename template.
|
|
void setTextureFilenameTemplate(const string& filenameTemplate)
|
|
{
|
|
_textureFilenameTemplate = (filenameTemplate.find("$EXTENSION") == string::npos) ?
|
|
filenameTemplate + ".$EXTENSION" : filenameTemplate;
|
|
}
|
|
|
|
/// Set texFilenameOverrides if template variable exists.
|
|
void setFilenameTemplateVarOverride(const string& key, const string& value)
|
|
{
|
|
if (_permittedOverrides.count(key))
|
|
{
|
|
_texTemplateOverrides[key] = value;
|
|
}
|
|
}
|
|
|
|
/// Set the output stream for reporting progress and warnings. Defaults to std::cout.
|
|
void setOutputStream(std::ostream* outputStream)
|
|
{
|
|
_outputStream = outputStream;
|
|
}
|
|
|
|
/// Return the output stream for reporting progress and warnings.
|
|
std::ostream* getOutputStream() const
|
|
{
|
|
return _outputStream;
|
|
}
|
|
|
|
/// Set whether to create a short name for baked images by hashing the baked image filenames
|
|
/// This is useful for file systems which may have a maximum limit on filename size.
|
|
/// By default names are not hashed.
|
|
void setHashImageNames(bool enable)
|
|
{
|
|
_hashImageNames = enable;
|
|
}
|
|
|
|
/// Return whether automatic baked texture resolution is set.
|
|
bool getHashImageNames() const
|
|
{
|
|
return _hashImageNames;
|
|
}
|
|
|
|
/// Set the minimum texcoords used in texture baking. Defaults to 0, 0.
|
|
void setTextureSpaceMin(const Vector2& min)
|
|
{
|
|
_textureSpaceMin = min;
|
|
}
|
|
|
|
/// Return the minimum texcoords used in texture baking.
|
|
Vector2 getTextureSpaceMin() const
|
|
{
|
|
return _textureSpaceMin;
|
|
}
|
|
|
|
/// Set the maximum texcoords used in texture baking. Defaults to 1, 1.
|
|
void setTextureSpaceMax(const Vector2& max)
|
|
{
|
|
_textureSpaceMax = max;
|
|
}
|
|
|
|
/// Return the maximum texcoords used in texture baking.
|
|
Vector2 getTextureSpaceMax() const
|
|
{
|
|
return _textureSpaceMax;
|
|
}
|
|
|
|
/// Set up the unit definitions to be used in baking.
|
|
void setupUnitSystem(DocumentPtr unitDefinitions);
|
|
|
|
/// Bake textures for all graph inputs of the given shader.
|
|
void bakeShaderInputs(NodePtr material, NodePtr shader, GenContext& context, const string& udim = EMPTY_STRING);
|
|
|
|
/// Bake a texture for the given graph output.
|
|
void bakeGraphOutput(OutputPtr output, GenContext& context, const StringMap& filenameTemplateMap);
|
|
|
|
/// Optimize baked textures before writing.
|
|
void optimizeBakedTextures(NodePtr shader);
|
|
|
|
/// Bake material to document in memory and write baked textures to disk.
|
|
DocumentPtr bakeMaterialToDoc(DocumentPtr doc, const FileSearchPath& searchPath, const string& materialPath,
|
|
const StringVec& udimSet, std::string& documentName);
|
|
|
|
/// Bake materials in the given document and write them to disk. If multiple documents are written,
|
|
/// then the given output filename will be used as a template.
|
|
void bakeAllMaterials(DocumentPtr doc, const FileSearchPath& searchPath, const FilePath& outputFileName);
|
|
|
|
/// Set whether to write a separate document per material when calling bakeAllMaterials.
|
|
/// By default separate documents are written.
|
|
void writeDocumentPerMaterial(bool value)
|
|
{
|
|
_writeDocumentPerMaterial = value;
|
|
}
|
|
|
|
string getValueStringFromColor(const Color4& color, const string& type);
|
|
|
|
protected:
|
|
class BakedImage
|
|
{
|
|
public:
|
|
FilePath filename;
|
|
Color4 uniformColor;
|
|
bool isUniform = false;
|
|
};
|
|
class BakedConstant
|
|
{
|
|
public:
|
|
Color4 color;
|
|
bool isDefault = false;
|
|
};
|
|
using BakedImageVec = vector<BakedImage>;
|
|
using BakedImageMap = std::unordered_map<OutputPtr, BakedImageVec>;
|
|
using BakedConstantMap = std::unordered_map<OutputPtr, BakedConstant>;
|
|
|
|
protected:
|
|
TextureBaker(unsigned int width, unsigned int height, Image::BaseType baseType, bool flipSavedImage);
|
|
|
|
// Populate file template variable naming map
|
|
StringMap initializeFileTemplateMap(InputPtr input, NodePtr shader, const string& udim = EMPTY_STRING);
|
|
|
|
// Find first occurence of variable in filename from start index onwards
|
|
size_t findVarInTemplate(const string& filename, const string& var, size_t start = 0);
|
|
|
|
// Generate a texture filename for the given graph output.
|
|
FilePath generateTextureFilename(const StringMap& fileTemplateMap);
|
|
|
|
// Create document that links shader outputs to a material.
|
|
DocumentPtr generateNewDocumentFromShader(NodePtr shader, const StringVec& udimSet);
|
|
|
|
// Write a baked image to disk, returning true if the write was successful.
|
|
bool writeBakedImage(const BakedImage& baked, ImagePtr image);
|
|
|
|
protected:
|
|
string _extension;
|
|
string _colorSpace;
|
|
string _distanceUnit;
|
|
bool _averageImages;
|
|
bool _optimizeConstants;
|
|
FilePath _outputImagePath;
|
|
string _bakedGraphName;
|
|
string _bakedGeomInfoName;
|
|
string _textureFilenameTemplate;
|
|
std::ostream* _outputStream;
|
|
bool _hashImageNames;
|
|
Vector2 _textureSpaceMin;
|
|
Vector2 _textureSpaceMax;
|
|
|
|
ShaderGeneratorPtr _generator;
|
|
ConstNodePtr _material;
|
|
ImagePtr _frameCaptureImage;
|
|
BakedImageMap _bakedImageMap;
|
|
BakedConstantMap _bakedConstantMap;
|
|
StringSet _permittedOverrides;
|
|
StringMap _texTemplateOverrides;
|
|
StringMap _bakedInputMap;
|
|
|
|
std::unordered_map<string, NodePtr> _worldSpaceNodes;
|
|
|
|
bool _flipSavedImage;
|
|
|
|
bool _writeDocumentPerMaterial;
|
|
DocumentPtr _bakedTextureDoc;
|
|
};
|
|
|
|
MATERIALX_NAMESPACE_END
|
|
|
|
#include <MaterialXRender/TextureBaker.inl>
|
|
|
|
#endif
|