diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.h b/lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.h index f256a41bdc..b7ea8f82c0 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.h +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.h @@ -47,7 +47,7 @@ class MAYAUSD_CORE_PUBLIC TopoNeutralGraph // Get the watch list gathered while traversing const WatchList& getWatchList() const; -private: +protected: mx::NodePtr cloneNode(const mx::Node& node, mx::GraphElement& container); mx::OutputPtr findNodeGraphOutput(const mx::Input& input, const std::string& outputName); std::string gatherChannels(const mx::Input& input); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt b/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt index 3da560745c..ab019a0506 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt +++ b/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt @@ -15,6 +15,7 @@ target_sources(${PROJECT_NAME} meshViewportCompute.cpp points.cpp proxyRenderDelegate.cpp + colorManagementPreferences.cpp render_delegate.cpp render_param.cpp sampler.cpp @@ -24,6 +25,7 @@ target_sources(${PROJECT_NAME} set(HEADERS proxyRenderDelegate.h + colorManagementPreferences.h ) # ----------------------------------------------------------------------------- diff --git a/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.cpp b/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.cpp new file mode 100644 index 0000000000..b89bf80faf --- /dev/null +++ b/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.cpp @@ -0,0 +1,141 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "colorManagementPreferences.h" + +#include +#include +#include + +#include + +namespace MAYAUSD_NS_DEF { + +// We will cache the color management preferences since they are used in many loops. +ColorManagementPreferences::~ColorManagementPreferences() { RemoveSinks(); } + +bool ColorManagementPreferences::Active() { return Get()._active; } + +const MString& ColorManagementPreferences::RenderingSpaceName() +{ + return Get()._renderingSpaceName; +} + +const MString& ColorManagementPreferences::sRGBName() { return Get()._sRGBName; } + +std::string ColorManagementPreferences::getFileRule(const std::string& path) +{ + MString colorRuleCmd; + colorRuleCmd.format("colorManagementFileRules -evaluate \"^1s\";", MString(path.c_str())); + return MGlobal::executeCommandStringResult(colorRuleCmd).asChar(); +} + +void ColorManagementPreferences::SetDirty() +{ + auto& self = InternalGet(); + self._dirty = true; +} + +void ColorManagementPreferences::MayaExit() +{ + auto& self = InternalGet(); + self.RemoveSinks(); +} + +ColorManagementPreferences::ColorManagementPreferences() = default; + +const ColorManagementPreferences& ColorManagementPreferences::Get() +{ + auto& self = InternalGet(); + self.Refresh(); + return self; +} +ColorManagementPreferences& ColorManagementPreferences::InternalGet() +{ + static ColorManagementPreferences _self; + return _self; +} + +void ColorManagementPreferences::RemoveSinks() +{ + for (auto id : _mayaColorManagementCallbackIds) { + MMessage::removeCallback(id); + } + _mayaColorManagementCallbackIds.clear(); +} + +void colorManagementRefreshCB(void*) { ColorManagementPreferences::SetDirty(); } + +void mayaExitingCB(void*) { ColorManagementPreferences::MayaExit(); } + +void ColorManagementPreferences::Refresh() +{ + if (_mayaColorManagementCallbackIds.empty()) { + // Monitor color management prefs + _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( + "colorMgtEnabledChanged", colorManagementRefreshCB, this)); + _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( + "colorMgtWorkingSpaceChanged", colorManagementRefreshCB, this)); + _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( + "colorMgtConfigChanged", colorManagementRefreshCB, this)); + _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( + "colorMgtConfigFilePathChanged", colorManagementRefreshCB, this)); + // The color management settings are quietly reset on file new: + _mayaColorManagementCallbackIds.push_back( + MSceneMessage::addCallback(MSceneMessage::kBeforeNew, colorManagementRefreshCB, this)); + _mayaColorManagementCallbackIds.push_back( + MSceneMessage::addCallback(MSceneMessage::kBeforeOpen, colorManagementRefreshCB, this)); + + // Cleanup on exit: + _mayaColorManagementCallbackIds.push_back( + MSceneMessage::addCallback(MSceneMessage::kMayaExiting, mayaExitingCB, this)); + } + + if (!_dirty) { + return; + } + _dirty = false; + + int isActive = 0; + MGlobal::executeCommand("colorManagementPrefs -q -cmEnabled", isActive, false, false); + if (!isActive) { + _active = false; + return; + } + + _active = true; + + _renderingSpaceName + = MGlobal::executeCommandStringResult("colorManagementPrefs -q -renderingSpaceName"); + + // Need some robustness around sRGB since not all OCIO configs declare it the same way: + const auto sRGBAliases + = std::set { "sRGB", "sRGB - Texture", + "srgb_tx", "Utility - sRGB - Texture", + "srgb_texture", "Input - Generic - sRGB - Texture" }; + + MStringArray allInputSpaces; + MGlobal::executeCommand( + "colorManagementPrefs -q -inputSpaceNames", allInputSpaces, false, false); + + for (auto&& spaceName : allInputSpaces) { + if (sRGBAliases.count(spaceName.asChar())) { + _sRGBName = spaceName; + break; + } + } +} + +} // namespace MAYAUSD_NS_DEF diff --git a/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.h b/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.h new file mode 100644 index 0000000000..a1522473de --- /dev/null +++ b/lib/mayaUsd/render/vp2RenderDelegate/colorManagementPreferences.h @@ -0,0 +1,84 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef COLOR_MANAGEMENT_PREFERENCES +#define COLOR_MANAGEMENT_PREFERENCES + +#include + +#include +#include + +#include + +namespace MAYAUSD_NS_DEF { + +/*! \brief Cache of color management preferences and queries. + + Getting the information involves calling MEL scripts, so we cache the results for better + performance. +*/ +class MAYAUSD_CORE_PUBLIC ColorManagementPreferences +{ +public: + ~ColorManagementPreferences(); + + /*! \brief Is color management active. + */ + static bool Active(); + + /*! \brief The current DCC rendering space name. + */ + static const MString& RenderingSpaceName(); + + /*! \brief The current DCC color space name for plain sRGB + + Color management config files can rename or alias the sRGB color space name. We try a few + common names and remember the first one that is found in the config. + */ + static const MString& sRGBName(); + + /*! \brief Returns the OCIO color space name according to config file rules. + + \param path The path of the file to be color managed. + */ + static std::string getFileRule(const std::string& path); + + /*! \brief Utility function to reset all cached data. + */ + static void SetDirty(); + + /*! \brief Utility function to reset all message handlers on exit. + */ + static void MayaExit(); + +private: + ColorManagementPreferences(); + static const ColorManagementPreferences& Get(); + static ColorManagementPreferences& InternalGet(); + + bool _dirty = true; + bool _active = false; + MString _renderingSpaceName; + MString _sRGBName; + std::vector _mayaColorManagementCallbackIds; + + void Refresh(); + void RemoveSinks(); +}; + +} // namespace MAYAUSD_NS_DEF + +#endif diff --git a/lib/mayaUsd/render/vp2RenderDelegate/material.cpp b/lib/mayaUsd/render/vp2RenderDelegate/material.cpp index 70abe48a73..fb58e6afc0 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/material.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/material.cpp @@ -22,6 +22,7 @@ #include "tokens.h" #include +#include #include #include #include @@ -238,126 +239,6 @@ TF_DEFINE_PRIVATE_TOKENS( ); // clang-format on -// We will cache the color management preferences since they are used in many loops. -class CMPrefs -{ -public: - ~CMPrefs() { RemoveSinks(); } - static bool Active() { return Get()._active; } - static const MString& RenderingSpaceName() { return Get()._renderingSpaceName; } - static const MString& sRGBName() { return Get()._sRGBName; } - static std::string getFileRule(const std::string& path) - { - MString colorRuleCmd; - colorRuleCmd.format("colorManagementFileRules -evaluate \"^1s\";", MString(path.c_str())); - return MGlobal::executeCommandStringResult(colorRuleCmd).asChar(); - } - - static void SetDirty() - { - auto& self = InternalGet(); - self._dirty = true; - } - - static void MayaExit() - { - auto& self = InternalGet(); - self.RemoveSinks(); - } - -private: - CMPrefs() = default; - static const CMPrefs& Get() - { - auto& self = InternalGet(); - self.Refresh(); - return self; - } - static CMPrefs& InternalGet() - { - static CMPrefs _self; - return _self; - } - bool _dirty = true; - bool _active = false; - MString _renderingSpaceName; - MString _sRGBName; - std::vector _mayaColorManagementCallbackIds; - MCallbackId _mayaExitingCB { 0 }; - - void Refresh(); - void RemoveSinks() - { - for (auto id : _mayaColorManagementCallbackIds) { - MMessage::removeCallback(id); - } - _mayaColorManagementCallbackIds.clear(); - MMessage::removeCallback(_mayaExitingCB); - } -}; - -void colorManagementRefreshCB(void*) { CMPrefs::SetDirty(); } - -void mayaExitingCB(void*) { CMPrefs::MayaExit(); } - -void CMPrefs::Refresh() -{ - if (_mayaColorManagementCallbackIds.empty()) { - // Monitor color management prefs - _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( - "colorMgtEnabledChanged", colorManagementRefreshCB, this)); - _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( - "colorMgtWorkingSpaceChanged", colorManagementRefreshCB, this)); - _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( - "colorMgtConfigChanged", colorManagementRefreshCB, this)); - _mayaColorManagementCallbackIds.push_back(MEventMessage::addEventCallback( - "colorMgtConfigFilePathChanged", colorManagementRefreshCB, this)); - // The color management settings are quietly reset on file new: - _mayaColorManagementCallbackIds.push_back( - MSceneMessage::addCallback(MSceneMessage::kBeforeNew, colorManagementRefreshCB, this)); - _mayaColorManagementCallbackIds.push_back( - MSceneMessage::addCallback(MSceneMessage::kBeforeOpen, colorManagementRefreshCB, this)); - - // Cleanup on exit: - _mayaExitingCB - = MSceneMessage::addCallback(MSceneMessage::kMayaExiting, mayaExitingCB, this); - } - - if (!_dirty) { - return; - } - _dirty = false; - - int isActive = 0; - MGlobal::executeCommand("colorManagementPrefs -q -cmEnabled", isActive, false, false); - if (!isActive) { - _active = false; - return; - } - - _active = true; - - _renderingSpaceName - = MGlobal::executeCommandStringResult("colorManagementPrefs -q -renderingSpaceName"); - - // Need some robustness around sRGB since not all OCIO configs declare it the same way: - const auto sRGBAliases - = std::set { "sRGB", "sRGB - Texture", - "srgb_tx", "Utility - sRGB - Texture", - "srgb_texture", "Input - Generic - sRGB - Texture" }; - - MStringArray allInputSpaces; - MGlobal::executeCommand( - "colorManagementPrefs -q -inputSpaceNames", allInputSpaces, false, false); - - for (auto&& spaceName : allInputSpaces) { - if (sRGBAliases.count(spaceName.asChar())) { - _sRGBName = spaceName; - break; - } - } -} - #ifdef WANT_MATERIALX_BUILD // clang-format off @@ -459,12 +340,11 @@ struct _MaterialXData // This environment variable is defined in USD: pxr\usd\usdMtlx\parser.cpp static const std::string env = TfGetenv("USDMTLX_PRIMARY_UV_NAME"); - std::string mainUvSetName = env.empty() ? UsdUtilsGetPrimaryUVSetName().GetString() : env; - - mx::OgsXmlGenerator::setPrimaryUVSetName(mainUvSetName); + _mainUvSetName = env.empty() ? UsdUtilsGetPrimaryUVSetName().GetString() : env; } MaterialX::FileSearchPath _mtlxSearchPath; //!< MaterialX library search path MaterialX::DocumentPtr _mtlxLibrary; //!< MaterialX library + std::string _mainUvSetName; //!< Main UV set name private: void _FixLibraryTangentInputs(MaterialX::DocumentPtr& mtlxLibrary); @@ -564,7 +444,7 @@ size_t _GenerateNetwork2TopoHash(const HdMaterialNetwork2& materialNetwork) } } #ifdef HAS_COLOR_MANAGEMENT_SUPPORT_API - if (CMPrefs::Active()) { + if (MayaUsd::ColorManagementPreferences::Active()) { // Explicit color management parameters affect topology: for (auto&& cmName : _mtlxKnownColorSpaceAttrs) { auto cmIt = node.parameters.find(cmName); @@ -599,7 +479,9 @@ size_t _GenerateNetwork2TopoHash(const HdMaterialNetwork2& materialNetwork) #ifdef HAS_COLOR_MANAGEMENT_SUPPORT_API if (hasTextureNode) { MayaUsd::hash_combine( - topoHash, std::hash {}(CMPrefs::RenderingSpaceName().asChar())); + topoHash, + std::hash {}( + MayaUsd::ColorManagementPreferences::RenderingSpaceName().asChar())); } #endif @@ -1161,7 +1043,7 @@ std::string _GenerateXMLString(const HdMaterialNetwork& materialNetwork, bool in #ifdef HAS_COLOR_MANAGEMENT_SUPPORT_API void _AddColorManagementFragments(HdMaterialNetwork& net) { - if (!CMPrefs::Active()) { + if (!MayaUsd::ColorManagementPreferences::Active()) { return; } @@ -1212,13 +1094,13 @@ void _AddColorManagementFragments(HdMaterialNetwork& net) if (resolvedPath.empty()) { continue; } - colorSpace = CMPrefs::getFileRule(resolvedPath).c_str(); + colorSpace = MayaUsd::ColorManagementPreferences::getFileRule(resolvedPath).c_str(); } else if (sourceColorSpace == _tokens->sRGB) { - if (CMPrefs::sRGBName().isEmpty()) { + if (MayaUsd::ColorManagementPreferences::sRGBName().isEmpty()) { // No alias found. Do not color correct... continue; } - colorSpace = CMPrefs::sRGBName(); + colorSpace = MayaUsd::ColorManagementPreferences::sRGBName(); } else if (sourceColorSpace == _tokens->raw) { // No cm necessary for raw: continue; @@ -2429,9 +2311,10 @@ void HdVP2Material::CompiledNetwork::_ApplyVP2Fixes( SdrShaderNodeConstPtr sdrNode = shaderReg.GetShaderNodeByIdentifier(outNode.identifier); #endif if (_IsUsdUVTexture(node)) { - outNode.identifier = TfToken( - HdVP2ShaderFragments::getUsdUVTextureFragmentName(CMPrefs::RenderingSpaceName()) - .asChar()); + outNode.identifier + = TfToken(HdVP2ShaderFragments::getUsdUVTextureFragmentName( + MayaUsd::ColorManagementPreferences::RenderingSpaceName()) + .asChar()); } else { if (!sdrNode) { TF_WARN("Could not find a shader node for <%s>", node.path.GetText()); @@ -2753,7 +2636,7 @@ TfToken _RequiresColorManagement( if (resolvedPath.empty()) { return {}; } - sourceColorSpace = CMPrefs::getFileRule(resolvedPath); + sourceColorSpace = MayaUsd::ColorManagementPreferences::getFileRule(resolvedPath); } if (sourceColorSpace == "Raw" || sourceColorSpace == "raw") { @@ -2867,7 +2750,7 @@ void HdVP2Material::CompiledNetwork::_ApplyMtlxVP2Fixes( for (const auto& c : cnxPair.second) { TfToken cmNodeDefId, cmInputName, cmOutputName; #ifdef HAS_COLOR_MANAGEMENT_SUPPORT_API - if (CMPrefs::Active()) { + if (MayaUsd::ColorManagementPreferences::Active()) { cmNodeDefId = _RequiresColorManagement( inNode, inNet.nodes.find(c.upstreamNode)->second, @@ -2881,7 +2764,7 @@ void HdVP2Material::CompiledNetwork::_ApplyMtlxVP2Fixes( if (!colorManagementType.IsEmpty()) { if (colorManagementCategory.empty()) { auto categoryIt = _mtlxColorCorrectCategoryMap.find( - CMPrefs::RenderingSpaceName().asChar()); + MayaUsd::ColorManagementPreferences::RenderingSpaceName().asChar()); if (categoryIt != _mtlxColorCorrectCategoryMap.end()) { colorManagementCategory = categoryIt->second; } @@ -3027,8 +2910,15 @@ MHWRender::MShaderInstance* HdVP2Material::CompiledNetwork::_CreateMaterialXShad return shaderInstance; } + // Enable changing texcoord to geompropvalue + const auto prevUVSetName = mx::OgsXmlGenerator::getPrimaryUVSetName(); + mx::OgsXmlGenerator::setPrimaryUVSetName(_GetMaterialXData()._mainUvSetName); + MaterialXMaya::OgsFragment ogsFragment(materialNode, crLibrarySearchPath); + // Restore previous UV set name + mx::OgsXmlGenerator::setPrimaryUVSetName(prevUVSetName); + // Explore the fragment for primvars: mx::ShaderPtr shader = ogsFragment.getShader(); const mx::VariableBlock& vertexInputs