From be011e320db0b328a57e097f1c73ee25d2a5432d Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Thu, 9 Dec 2021 15:37:39 +1100 Subject: [PATCH 1/7] Added USD preview surface shader override for CPV display --- lib/usd/pxrUsdPreviewSurface/CMakeLists.txt | 1 + .../usdPreviewSurfacePlugin.cpp | 13 +- .../usdPreviewSurfaceShaderOverride.cpp | 204 ++++++++++++++++++ .../usdPreviewSurfaceShaderOverride.h | 96 +++++++++ 4 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp create mode 100644 lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h diff --git a/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt b/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt index 2a72ff2e48..9acf63c97c 100644 --- a/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt +++ b/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${TARGET_NAME} usdPreviewSurface.cpp usdPreviewSurfacePlugin.cpp usdPreviewSurfaceReader.cpp + usdPreviewSurfaceShaderOverride.cpp usdPreviewSurfaceShadingNodeOverride.cpp usdPreviewSurfaceWriter.cpp ) diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp index ebd1a77646..a0ad43045f 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp @@ -17,6 +17,7 @@ #include "usdPreviewSurface.h" #include "usdPreviewSurfaceReader.h" +#include "usdPreviewSurfaceShaderOverride.h" #include "usdPreviewSurfaceShadingNodeOverride.h" #include "usdPreviewSurfaceWriter.h" @@ -71,6 +72,12 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( drawDbClassification, registrantId, PxrMayaUsdPreviewSurfaceShadingNodeOverride::creator); CHECK_MSTATUS(status); + status = MHWRender::MDrawRegistry::registerShaderOverrideCreator( + drawDbClassification, + registrantId + "ShaderOverride", + PxrMayaUsdPreviewSurfaceShaderOverride::creator); + CHECK_MSTATUS(status); + return status; } @@ -93,7 +100,11 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::finalize( deregisterFragments(); - MStatus status = MHWRender::MDrawRegistry::deregisterSurfaceShadingNodeOverrideCreator( + MStatus status = MHWRender::MDrawRegistry::deregisterShaderOverrideCreator( + drawDbClassification, registrantId); + CHECK_MSTATUS(status); + + status = MHWRender::MDrawRegistry::deregisterSurfaceShadingNodeOverrideCreator( drawDbClassification, registrantId); CHECK_MSTATUS(status); diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp new file mode 100644 index 0000000000..8e666a5603 --- /dev/null +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp @@ -0,0 +1,204 @@ +// +// Copyright 2021 Animal Logic +// +// 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 "usdPreviewSurfaceShaderOverride.h" + +#include + +#include + +#include +#include + +PXR_NAMESPACE_OPEN_SCOPE + +static MStatus populateShaderManager(const MShaderManager* shaderMgr) +{ + MRenderer* renderer = MRenderer::theRenderer(); + if (!renderer) + return MS::kFailure; + shaderMgr = renderer->getShaderManager(); + return shaderMgr ? MS::kSuccess : MS::kFailure; +} + +MPxShaderOverride* PxrMayaUsdPreviewSurfaceShaderOverride::creator(const MObject& obj) +{ + return new PxrMayaUsdPreviewSurfaceShaderOverride(obj); +} + +PxrMayaUsdPreviewSurfaceShaderOverride::PxrMayaUsdPreviewSurfaceShaderOverride(const MObject& obj) + : MPxShaderOverride(obj) +{ +} + +PxrMayaUsdPreviewSurfaceShaderOverride::~PxrMayaUsdPreviewSurfaceShaderOverride() +{ + const MShaderManager* shaderMgr = nullptr; + if (m_shaderInstance && populateShaderManager(shaderMgr)) { + shaderMgr->releaseShader(m_shaderInstance); + } +} + +MHWRender::DrawAPI PxrMayaUsdPreviewSurfaceShaderOverride::supportedDrawAPIs() const +{ + return MHWRender::kAllDevices; +} + +bool PxrMayaUsdPreviewSurfaceShaderOverride::rebuildAlways() { return true; } + +#if MAYA_API_VERSION >= 20220000 +MString PxrMayaUsdPreviewSurfaceShaderOverride::initialize( + const MInitContext& initContext, + MSharedPtr& data) +#else +MString PxrMayaUsdPreviewSurfaceShaderOverride::initialize( + const MInitContext& initContext, + MInitFeedback& data) +#endif +{ + // Define the geometry requirements for the mayaCPVInput fragment + addGeometryRequirement({ {}, MGeometry::kNormal, MGeometry::kFloat, 3 }); + addGeometryRequirement({ {}, MGeometry::kColor, MGeometry::kFloat, 4 }); + + const MShaderManager* shaderMgr = nullptr; + if (!m_shaderInstance && populateShaderManager(shaderMgr)) { + // Get an instance of the USD preview surface fragment shader + m_shaderInstance = shaderMgr->getFragmentShader( + HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText(), + "outSurfaceFinal", + true); + } + + return MPxShaderOverride::initialize(initContext, data); +} + +void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) +{ + // Update the cached attributes for the node + MStatus status; + MFnDependencyNode node(obj, &status); + if (!status) + return; + + node.findPlug("diffuseColorR", true).getValue(m_diffuseColor[0]); + node.findPlug("diffuseColorG", true).getValue(m_diffuseColor[1]); + node.findPlug("diffuseColorB", true).getValue(m_diffuseColor[2]); + + node.findPlug("emissiveColorR", true).getValue(m_emissiveColor[0]); + node.findPlug("emissiveColorG", true).getValue(m_emissiveColor[1]); + node.findPlug("emissiveColorB", true).getValue(m_emissiveColor[2]); + + node.findPlug("occlusion", true).getValue(m_occlusion); + node.findPlug("opacity", true).getValue(m_opacity); + node.findPlug("opacityThreshold", true).getValue(m_opacityThreshold); + node.findPlug("ior", true).getValue(m_ior); + node.findPlug("metallic", true).getValue(m_metallic); + node.findPlug("roughness", true).getValue(m_roughness); + + node.findPlug("specularColorR", true).getValue(m_specularColor[0]); + node.findPlug("specularColorG", true).getValue(m_specularColor[1]); + node.findPlug("specularColorB", true).getValue(m_specularColor[2]); + + node.findPlug("clearcoat", true).getValue(m_clearcoat); + node.findPlug("clearcoatRoughness", true).getValue(m_clearcoatRoughness); + node.findPlug("displacement", true).getValue(m_displacement); + + node.findPlug("normal0", true).getValue(m_normal[0]); + node.findPlug("normal1", true).getValue(m_normal[1]); + node.findPlug("normal2", true).getValue(m_normal[2]); + + node.findPlug("useSpecularWorkflow", true).getValue(m_useSpecularWorkflow); + node.findPlug("caching", true).getValue(m_caching); + node.findPlug("frozen", true).getValue(m_frozen); +} + +void PxrMayaUsdPreviewSurfaceShaderOverride::updateDevice() +{ + if (!m_shaderInstance) + return; + + // Copy the cached attributes from the node to the shader instance + m_shaderInstance->setArrayParameter("diffuseColor", m_diffuseColor, 3); + m_shaderInstance->setArrayParameter("emissiveColor", m_emissiveColor, 3); + m_shaderInstance->setParameter("occlusion", m_occlusion); + m_shaderInstance->setParameter("opacity", m_opacity); + m_shaderInstance->setParameter("opacityThreshold", m_opacityThreshold); + m_shaderInstance->setParameter("ior", m_ior); + m_shaderInstance->setParameter("metallic", m_metallic); + m_shaderInstance->setParameter("roughness", m_roughness); + m_shaderInstance->setArrayParameter("specularColor", m_specularColor, 3); + m_shaderInstance->setParameter("clearcoat", m_clearcoat); + m_shaderInstance->setParameter("clearcoatRoughness", m_clearcoatRoughness); + m_shaderInstance->setParameter("displacement", m_displacement); + m_shaderInstance->setArrayParameter("normal", m_normal, 3); + + m_shaderInstance->setParameter("useSpecularWorkflow", m_useSpecularWorkflow); + m_shaderInstance->setParameter("caching", m_caching); + m_shaderInstance->setParameter("frozen", m_frozen); + + // Set the CPV inputs to the shader instance + m_shaderInstance->addInputFragment("mayaCPVInput", "outColor", "diffuseColor"); + m_shaderInstance->addInputFragment("mayaCPVInput", "outTransparency", "dummyTransparency"); + m_shaderInstance->setIsTransparent(true); +} + +bool PxrMayaUsdPreviewSurfaceShaderOverride::handlesDraw(MDrawContext& context) +{ + // Handle draw on non-overriden color passes + const MPassContext& passCtx = context.getPassContext(); + const MStringArray& passSemantics = passCtx.passSemantics(); + for (const MString& semantic : passSemantics) { + if (semantic == MPassContext::kColorPassSemantic && !passCtx.hasShaderOverride()) { + return true; + } + } + return false; +} + +MShaderInstance* PxrMayaUsdPreviewSurfaceShaderOverride::shaderInstance(MDrawContext& context) const +{ + return m_shaderInstance; +} + +void PxrMayaUsdPreviewSurfaceShaderOverride::activateKey(MDrawContext& context, const MString& key) +{ + if (!m_shaderInstance) + return; + m_shaderInstance->updateParameters(context); + m_shaderInstance->bind(context); +} + +bool PxrMayaUsdPreviewSurfaceShaderOverride::draw( + MDrawContext& context, + const MRenderItemList& renderItemList) const +{ + if (m_shaderInstance) { + const unsigned int passCount = m_shaderInstance->getPassCount(context); + for (unsigned int i = 0; i < passCount; i++) { + m_shaderInstance->activatePass(context, i); + MPxShaderOverride::drawGeometry(context); + } + } + return true; +} + +void PxrMayaUsdPreviewSurfaceShaderOverride::terminateKey(MDrawContext& context, const MString& key) +{ + if (m_shaderInstance) + m_shaderInstance->unbind(context); +} + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h new file mode 100644 index 0000000000..6cddf0e5cf --- /dev/null +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h @@ -0,0 +1,96 @@ +// +// Copyright 2021 Animal Logic +// +// 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 PXRUSDPREVIEWSURFACE_USD_PREVIEW_SURFACE_SHADER_OVERRIDE_H +#define PXRUSDPREVIEWSURFACE_USD_PREVIEW_SURFACE_SHADER_OVERRIDE_H + +#include "api.h" + +#include + +#include +#include + +PXR_NAMESPACE_OPEN_SCOPE + +class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride +{ +public: + PXRUSDPREVIEWSURFACE_API + static MPxShaderOverride* creator(const MObject& obj); + + PXRUSDPREVIEWSURFACE_API + ~PxrMayaUsdPreviewSurfaceShaderOverride() override; + + PXRUSDPREVIEWSURFACE_API + MHWRender::DrawAPI supportedDrawAPIs() const override; + + PXRUSDPREVIEWSURFACE_API + bool rebuildAlways() override; + + PXRUSDPREVIEWSURFACE_API +#if MAYA_API_VERSION >= 20220000 + MString initialize(const MInitContext& initContext, MSharedPtr& userData) override; +#else + MString initialize(const MInitContext& initContext, MInitFeedback& initFeedback) override; +#endif + + PXRUSDPREVIEWSURFACE_API + void updateDG(MObject obj) override; + + PXRUSDPREVIEWSURFACE_API + void updateDevice() override; + + PXRUSDPREVIEWSURFACE_API + bool handlesDraw(MDrawContext& context) override; + + PXRUSDPREVIEWSURFACE_API + MShaderInstance* shaderInstance(MDrawContext& context) const override; + + PXRUSDPREVIEWSURFACE_API + void activateKey(MDrawContext& context, const MString& key) override; + + PXRUSDPREVIEWSURFACE_API + bool draw(MDrawContext& context, const MRenderItemList& renderItemList) const override; + + PXRUSDPREVIEWSURFACE_API + void terminateKey(MDrawContext& context, const MString& key) override; + +private: + PxrMayaUsdPreviewSurfaceShaderOverride(const MObject& obj); + + MShaderInstance* m_shaderInstance = nullptr; + + float m_diffuseColor[3]; + float m_emissiveColor[3]; + float m_occlusion; + float m_opacity; + float m_opacityThreshold; + float m_ior; + float m_metallic; + float m_roughness; + float m_specularColor[3]; + float m_clearcoat; + float m_clearcoatRoughness; + float m_displacement; + float m_normal[3]; + bool m_useSpecularWorkflow; + bool m_caching; + bool m_frozen; +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif From 8f6de456db3c84f9ba7435686d29a59146b17dfd Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Fri, 10 Dec 2021 17:06:21 +1100 Subject: [PATCH 2/7] Added option for CPV display on USD preview surface shader --- .../AEusdPreviewSurfaceTemplate.mel | 1 + .../pxrUsdPreviewSurface/usdPreviewSurface.cpp | 15 +++++++++++++++ lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h | 1 + .../usdPreviewSurfaceShaderOverride.cpp | 5 ++++- .../usdPreviewSurfaceShaderOverride.h | 1 + 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel index b207ce6324..dc1992edb2 100644 --- a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel +++ b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel @@ -42,6 +42,7 @@ global proc AE${PREVIEWSURFACE_MAYA_TYPE_NAME}Template(string $nodeName) editorTemplate -addControl "occlusion"; editorTemplate -addControl "opacity"; editorTemplate -addControl "opacityThreshold"; + editorTemplate -addControl "displayCPV"; editorTemplate -beginLayout "Specular" -collapse false; editorTemplate -addControl "useSpecularWorkflow" diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp index 05366015ec..e70c47b1a5 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp @@ -76,6 +76,7 @@ MStatus PxrMayaUsdPreviewSurface::initialize() MObject opacityThresholdAttr; MObject roughnessAttr; MObject specularColorAttr; + MObject displayCPVAttr; MObject useSpecularWorkflowAttr; MObject outColorAttr; MObject outTransparencyAttr; @@ -290,6 +291,18 @@ MStatus PxrMayaUsdPreviewSurface::initialize() status = addAttribute(specularColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); + displayCPVAttr = numericAttrFn.create( + PxrMayaUsdPreviewSurfaceTokens->DisplayCPVAttrName.GetText(), + "cpv", + MFnNumericData::kBoolean, + 0.0, + &status); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = numericAttrFn.setAffectsAppearance(true); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = addAttribute(displayCPVAttr); + CHECK_MSTATUS_AND_RETURN_IT(status); + useSpecularWorkflowAttr = numericAttrFn.create( PxrMayaUsdPreviewSurfaceTokens->UseSpecularWorkflowAttrName.GetText(), "usw", @@ -383,6 +396,8 @@ MStatus PxrMayaUsdPreviewSurface::initialize() CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(specularColorAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); + status = attributeAffects(displayCPVAttr, outColorAttr); + CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(useSpecularWorkflowAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h index 1d4d45b121..6d6b0357a1 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h @@ -48,6 +48,7 @@ PXR_NAMESPACE_OPEN_SCOPE ((OpacityThresholdAttrName, "opacityThreshold")) \ ((RoughnessAttrName, "roughness")) \ ((SpecularColorAttrName, "specularColor")) \ + ((DisplayCPVAttrName, "displayCPV")) \ ((UseSpecularWorkflowAttrName, "useSpecularWorkflow")) \ ((OutColorAttrName, "outColor")) \ ((OutTransparencyAttrName, "outTransparency")) \ diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp index 8e666a5603..6be7847d8a 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp @@ -120,6 +120,7 @@ void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) node.findPlug("normal1", true).getValue(m_normal[1]); node.findPlug("normal2", true).getValue(m_normal[2]); + node.findPlug("displayCPV", true).getValue(m_displayCPV); node.findPlug("useSpecularWorkflow", true).getValue(m_useSpecularWorkflow); node.findPlug("caching", true).getValue(m_caching); node.findPlug("frozen", true).getValue(m_frozen); @@ -149,7 +150,9 @@ void PxrMayaUsdPreviewSurfaceShaderOverride::updateDevice() m_shaderInstance->setParameter("caching", m_caching); m_shaderInstance->setParameter("frozen", m_frozen); - // Set the CPV inputs to the shader instance + // Set the CPV inputs to the shader instance if enabled + if (!m_displayCPV) + return; m_shaderInstance->addInputFragment("mayaCPVInput", "outColor", "diffuseColor"); m_shaderInstance->addInputFragment("mayaCPVInput", "outTransparency", "dummyTransparency"); m_shaderInstance->setIsTransparent(true); diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h index 6cddf0e5cf..482ce8dab4 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h @@ -86,6 +86,7 @@ class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride float m_clearcoatRoughness; float m_displacement; float m_normal[3]; + bool m_displayCPV; bool m_useSpecularWorkflow; bool m_caching; bool m_frozen; From 7a18214a41ae04916b75a7981c62b65a1966122d Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Tue, 14 Dec 2021 14:22:14 +1100 Subject: [PATCH 3/7] Added non-textured shader for USD preview surface shader override --- .../usdPreviewSurfacePlugin.cpp | 9 +- .../usdPreviewSurfaceShaderOverride.cpp | 140 +++++++++++++----- .../usdPreviewSurfaceShaderOverride.h | 10 +- 3 files changed, 116 insertions(+), 43 deletions(-) diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp index a0ad43045f..2bd33511b1 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp @@ -37,8 +37,9 @@ PXR_NAMESPACE_OPEN_SCOPE namespace { -TfToken::Set _registeredTypeNames; -} +TfToken::Set _registeredTypeNames; +static constexpr char shaderOverrideIdSuffix[] = "ShaderOverride"; +} // namespace /* static */ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( MFnPlugin& plugin, @@ -74,7 +75,7 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( status = MHWRender::MDrawRegistry::registerShaderOverrideCreator( drawDbClassification, - registrantId + "ShaderOverride", + registrantId + shaderOverrideIdSuffix, PxrMayaUsdPreviewSurfaceShaderOverride::creator); CHECK_MSTATUS(status); @@ -101,7 +102,7 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::finalize( deregisterFragments(); MStatus status = MHWRender::MDrawRegistry::deregisterShaderOverrideCreator( - drawDbClassification, registrantId); + drawDbClassification, registrantId + shaderOverrideIdSuffix); CHECK_MSTATUS(status); status = MHWRender::MDrawRegistry::deregisterSurfaceShadingNodeOverrideCreator( diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp index 6be7847d8a..c67054c1e0 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp @@ -16,6 +16,8 @@ #include "usdPreviewSurfaceShaderOverride.h" +#include "usdPreviewSurfacePlugin.h" + #include #include @@ -28,14 +30,32 @@ PXR_NAMESPACE_OPEN_SCOPE static MStatus populateShaderManager(const MShaderManager* shaderMgr) { MRenderer* renderer = MRenderer::theRenderer(); - if (!renderer) - return MS::kFailure; - shaderMgr = renderer->getShaderManager(); - return shaderMgr ? MS::kSuccess : MS::kFailure; + if (renderer) { + shaderMgr = renderer->getShaderManager(); + if (shaderMgr) + return MS::kSuccess; + } + TF_RUNTIME_ERROR("Failed to populate shader manager."); + return MS::kFailure; +} + +inline static MShaderInstance* getPreviewSurfaceShader(const MShaderManager* shaderMgr) +{ + return shaderMgr->getFragmentShader( + HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText(), "outSurfaceFinal", true); +} + +inline static MShaderInstance* +cloneOrCreateInstance(const MShaderManager* shaderMgr, MShaderInstance* instance) +{ + // Clone the shader instance or create a new one + return instance ? instance->clone() : getPreviewSurfaceShader(shaderMgr); } MPxShaderOverride* PxrMayaUsdPreviewSurfaceShaderOverride::creator(const MObject& obj) { + // Make sure the shader fragments have been registered before instantiating the override + PxrMayaUsdPreviewSurfacePlugin::registerFragments(); return new PxrMayaUsdPreviewSurfaceShaderOverride(obj); } @@ -46,9 +66,17 @@ PxrMayaUsdPreviewSurfaceShaderOverride::PxrMayaUsdPreviewSurfaceShaderOverride(c PxrMayaUsdPreviewSurfaceShaderOverride::~PxrMayaUsdPreviewSurfaceShaderOverride() { + // Release and clear all held shader instances const MShaderManager* shaderMgr = nullptr; - if (m_shaderInstance && populateShaderManager(shaderMgr)) { - shaderMgr->releaseShader(m_shaderInstance); + if (populateShaderManager(shaderMgr)) { + if (m_shaderInstanceNonTextured) { + shaderMgr->releaseShader(m_shaderInstanceNonTextured); + m_shaderInstanceNonTextured = nullptr; + } + if (m_shaderInstance) { + shaderMgr->releaseShader(m_shaderInstance); + m_shaderInstance = nullptr; + } } } @@ -73,18 +101,26 @@ MString PxrMayaUsdPreviewSurfaceShaderOverride::initialize( addGeometryRequirement({ {}, MGeometry::kNormal, MGeometry::kFloat, 3 }); addGeometryRequirement({ {}, MGeometry::kColor, MGeometry::kFloat, 4 }); + // Create instances of the USD preview surface fragment shader const MShaderManager* shaderMgr = nullptr; - if (!m_shaderInstance && populateShaderManager(shaderMgr)) { - // Get an instance of the USD preview surface fragment shader - m_shaderInstance = shaderMgr->getFragmentShader( - HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText(), - "outSurfaceFinal", - true); - } + if (populateShaderManager(shaderMgr)) { + if (!m_shaderInstanceNonTextured) + m_shaderInstanceNonTextured = getPreviewSurfaceShader(shaderMgr); + if (!m_shaderInstance) { + m_shaderInstance = cloneOrCreateInstance(shaderMgr, m_shaderInstanceNonTextured); + } + } return MPxShaderOverride::initialize(initContext, data); } +MShaderInstance* +PxrMayaUsdPreviewSurfaceShaderOverride::nonTexturedShaderInstance(bool& monitorNode) const +{ + monitorNode = true; // TODO why is this not running the update loop?? + return m_shaderInstanceNonTextured; +} + void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) { // Update the cached attributes for the node @@ -120,6 +156,8 @@ void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) node.findPlug("normal1", true).getValue(m_normal[1]); node.findPlug("normal2", true).getValue(m_normal[2]); + // Store previous display value + m_previousDisplayCPV = m_displayCPV; node.findPlug("displayCPV", true).getValue(m_displayCPV); node.findPlug("useSpecularWorkflow", true).getValue(m_useSpecularWorkflow); node.findPlug("caching", true).getValue(m_caching); @@ -128,34 +166,60 @@ void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) void PxrMayaUsdPreviewSurfaceShaderOverride::updateDevice() { - if (!m_shaderInstance) + // Recreate the textured shader if the CPV display value changed or does not exist + const MShaderManager* shaderMgr = nullptr; + if ((m_displayCPV != m_previousDisplayCPV || !m_shaderInstance) + && populateShaderManager(shaderMgr)) { + if (m_shaderInstance) { + shaderMgr->releaseShader(m_shaderInstance); + m_shaderInstance = nullptr; + } + + // Rebuild the textured shader + m_shaderInstance = cloneOrCreateInstance(shaderMgr, m_shaderInstanceNonTextured); + if (!m_shaderInstance) + TF_RUNTIME_ERROR("Failed to recreate textured shader instance."); + } + + // Update the parameters for each shader instance + setShaderParams(m_shaderInstanceNonTextured); + setShaderParams(m_shaderInstance, m_displayCPV); +} + +void PxrMayaUsdPreviewSurfaceShaderOverride::setShaderParams( + MShaderInstance*& shaderInstance, + bool displayCVP) +{ + if (!shaderInstance) return; + if (displayCVP) { + // Set the CPV inputs to the shader instance + shaderInstance->addInputFragment("mayaCPVInput", "outColor", "diffuseColor"); + shaderInstance->addInputFragment("mayaCPVInput", "outTransparency", "dummyTransparency"); + shaderInstance->setIsTransparent(true); + } else { + shaderInstance->setParameter("diffuseColor", &m_diffuseColor[0]); + shaderInstance->setParameter("dummyTransparency", 0.f); + shaderInstance->setIsTransparent(false); + } + // Copy the cached attributes from the node to the shader instance - m_shaderInstance->setArrayParameter("diffuseColor", m_diffuseColor, 3); - m_shaderInstance->setArrayParameter("emissiveColor", m_emissiveColor, 3); - m_shaderInstance->setParameter("occlusion", m_occlusion); - m_shaderInstance->setParameter("opacity", m_opacity); - m_shaderInstance->setParameter("opacityThreshold", m_opacityThreshold); - m_shaderInstance->setParameter("ior", m_ior); - m_shaderInstance->setParameter("metallic", m_metallic); - m_shaderInstance->setParameter("roughness", m_roughness); - m_shaderInstance->setArrayParameter("specularColor", m_specularColor, 3); - m_shaderInstance->setParameter("clearcoat", m_clearcoat); - m_shaderInstance->setParameter("clearcoatRoughness", m_clearcoatRoughness); - m_shaderInstance->setParameter("displacement", m_displacement); - m_shaderInstance->setArrayParameter("normal", m_normal, 3); - - m_shaderInstance->setParameter("useSpecularWorkflow", m_useSpecularWorkflow); - m_shaderInstance->setParameter("caching", m_caching); - m_shaderInstance->setParameter("frozen", m_frozen); - - // Set the CPV inputs to the shader instance if enabled - if (!m_displayCPV) - return; - m_shaderInstance->addInputFragment("mayaCPVInput", "outColor", "diffuseColor"); - m_shaderInstance->addInputFragment("mayaCPVInput", "outTransparency", "dummyTransparency"); - m_shaderInstance->setIsTransparent(true); + shaderInstance->setParameter("emissiveColor", &m_emissiveColor[0]); + shaderInstance->setParameter("occlusion", m_occlusion); + shaderInstance->setParameter("opacity", m_opacity); + shaderInstance->setParameter("opacityThreshold", m_opacityThreshold); + shaderInstance->setParameter("ior", m_ior); + shaderInstance->setParameter("metallic", m_metallic); + shaderInstance->setParameter("roughness", m_roughness); + shaderInstance->setParameter("specularColor", &m_specularColor[0]); + shaderInstance->setParameter("clearcoat", m_clearcoat); + shaderInstance->setParameter("clearcoatRoughness", m_clearcoatRoughness); + shaderInstance->setParameter("displacement", m_displacement); + shaderInstance->setParameter("normal", &m_normal[0]); + shaderInstance->setParameter("useSpecularWorkflow", m_useSpecularWorkflow); + shaderInstance->setParameter("caching", m_caching); + shaderInstance->setParameter("frozen", m_frozen); } bool PxrMayaUsdPreviewSurfaceShaderOverride::handlesDraw(MDrawContext& context) diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h index 482ce8dab4..8f18c4cb15 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h @@ -47,6 +47,9 @@ class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride MString initialize(const MInitContext& initContext, MInitFeedback& initFeedback) override; #endif + PXRUSDPREVIEWSURFACE_API + MShaderInstance* nonTexturedShaderInstance(bool& monitorNode) const override; + PXRUSDPREVIEWSURFACE_API void updateDG(MObject obj) override; @@ -71,8 +74,12 @@ class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride private: PxrMayaUsdPreviewSurfaceShaderOverride(const MObject& obj); + void setShaderParams(MShaderInstance*& shaderInstance, bool displayCVP = false); + MShaderInstance* m_shaderInstance = nullptr; + MShaderInstance* m_shaderInstanceNonTextured = nullptr; + float m_diffuseColor[3]; float m_emissiveColor[3]; float m_occlusion; @@ -86,10 +93,11 @@ class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride float m_clearcoatRoughness; float m_displacement; float m_normal[3]; - bool m_displayCPV; bool m_useSpecularWorkflow; bool m_caching; bool m_frozen; + bool m_displayCPV; + bool m_previousDisplayCPV; }; PXR_NAMESPACE_CLOSE_SCOPE From 75118d7e565801ee746604da12e67fd03856307b Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Wed, 19 Jan 2022 11:05:53 +1100 Subject: [PATCH 4/7] Separated out CPV color shading into external CPVColor node --- .../AEusdPreviewSurfaceTemplate.mel | 1 - lib/usd/pxrUsdPreviewSurface/CMakeLists.txt | 2 +- lib/usd/pxrUsdPreviewSurface/cpvColor.cpp | 93 ++++++ lib/usd/pxrUsdPreviewSurface/cpvColor.h | 82 ++++++ .../usdPreviewSurface.cpp | 15 - .../pxrUsdPreviewSurface/usdPreviewSurface.h | 1 - .../usdPreviewSurfacePlugin.cpp | 35 ++- .../usdPreviewSurfaceShaderOverride.cpp | 271 ------------------ .../usdPreviewSurfaceShaderOverride.h | 105 ------- 9 files changed, 202 insertions(+), 403 deletions(-) create mode 100644 lib/usd/pxrUsdPreviewSurface/cpvColor.cpp create mode 100644 lib/usd/pxrUsdPreviewSurface/cpvColor.h delete mode 100644 lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp delete mode 100644 lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h diff --git a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel index dc1992edb2..b207ce6324 100644 --- a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel +++ b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel @@ -42,7 +42,6 @@ global proc AE${PREVIEWSURFACE_MAYA_TYPE_NAME}Template(string $nodeName) editorTemplate -addControl "occlusion"; editorTemplate -addControl "opacity"; editorTemplate -addControl "opacityThreshold"; - editorTemplate -addControl "displayCPV"; editorTemplate -beginLayout "Specular" -collapse false; editorTemplate -addControl "useSpecularWorkflow" diff --git a/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt b/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt index 9acf63c97c..1c0d2bd94a 100644 --- a/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt +++ b/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt @@ -30,10 +30,10 @@ add_library(${TARGET_NAME} SHARED) # ----------------------------------------------------------------------------- target_sources(${TARGET_NAME} PRIVATE + cpvColor.cpp usdPreviewSurface.cpp usdPreviewSurfacePlugin.cpp usdPreviewSurfaceReader.cpp - usdPreviewSurfaceShaderOverride.cpp usdPreviewSurfaceShadingNodeOverride.cpp usdPreviewSurfaceWriter.cpp ) diff --git a/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp b/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp new file mode 100644 index 0000000000..87ea829565 --- /dev/null +++ b/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp @@ -0,0 +1,93 @@ +// +// Copyright 2021 Animal Logic +// +// 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 "cpvColor.h" + +#include + +PXR_NAMESPACE_OPEN_SCOPE + +static const MString cpvInputFragmentName("mayaCPVInput"); + +const MTypeId CPVColor::id(0x58000098); +MObject CPVColor::aUVCoord; +MObject CPVColor::aOutColor; +MObject CPVColor::aOutAlpha; + +void* CPVColor::creator() { return new CPVColor(); } + +CPVColor::CPVColor() { } + +CPVColor::~CPVColor() { } + +MStatus CPVColor::initialize() +{ + // Define implicit shading network attributes + MFnNumericAttribute nAttr; + MObject uCoord = nAttr.create("uCoord", "u", MFnNumericData::kFloat); + MObject vCoord = nAttr.create("vCoord", "v", MFnNumericData::kFloat); + aUVCoord = nAttr.create("uvCoord", "uv", uCoord, vCoord); + CHECK_MSTATUS(nAttr.setKeyable(true)); + CHECK_MSTATUS(nAttr.setStorable(true)); + CHECK_MSTATUS(nAttr.setReadable(true)); + CHECK_MSTATUS(nAttr.setWritable(true)); + CHECK_MSTATUS(nAttr.setHidden(true)); + aOutColor = nAttr.createColor("outColor", "oc"); + CHECK_MSTATUS(nAttr.setKeyable(false)); + CHECK_MSTATUS(nAttr.setStorable(false)); + CHECK_MSTATUS(nAttr.setReadable(true)); + CHECK_MSTATUS(nAttr.setWritable(false)); + aOutAlpha = nAttr.create("outAlpha", "oa", MFnNumericData::kFloat); + CHECK_MSTATUS(nAttr.setKeyable(false)); + CHECK_MSTATUS(nAttr.setStorable(false)); + CHECK_MSTATUS(nAttr.setReadable(true)); + CHECK_MSTATUS(nAttr.setWritable(false)); + + // Add attributes and setup attribute affecting relationships + CHECK_MSTATUS(addAttribute(aUVCoord)); + CHECK_MSTATUS(addAttribute(aOutColor)); + CHECK_MSTATUS(addAttribute(aOutAlpha)); + CHECK_MSTATUS(attributeAffects(aUVCoord, aOutColor)); + CHECK_MSTATUS(attributeAffects(aUVCoord, aOutAlpha)); + +MPxNode::SchedulingType CPVColor::schedulingType() const { return SchedulingType::kParallel; } + return MS::kSuccess; +} + +MHWRender::MPxShadingNodeOverride* CPVColorShadingNodeOverride::creator(const MObject& obj) +{ + return new CPVColorShadingNodeOverride(obj); +} + +CPVColorShadingNodeOverride::CPVColorShadingNodeOverride(const MObject& obj) + : MPxShadingNodeOverride(obj) +{ +} + +CPVColorShadingNodeOverride::~CPVColorShadingNodeOverride() { } + +MHWRender::DrawAPI CPVColorShadingNodeOverride::supportedDrawAPIs() const +{ + return MHWRender::kOpenGL | MHWRender::kDirectX11 | MHWRender::kOpenGLCoreProfile; +} + +MString CPVColorShadingNodeOverride::fragmentName() const +{ + // Delegate the maya standard CPV input fragment to drive output + return cpvInputFragmentName; +} + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/usd/pxrUsdPreviewSurface/cpvColor.h b/lib/usd/pxrUsdPreviewSurface/cpvColor.h new file mode 100644 index 0000000000..cb6b440cb4 --- /dev/null +++ b/lib/usd/pxrUsdPreviewSurface/cpvColor.h @@ -0,0 +1,82 @@ +// +// Copyright 2021 Animal Logic +// +// 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 PXRUSDPREVIEWSURFACE_CPVCOLOR_H +#define PXRUSDPREVIEWSURFACE_CPVCOLOR_H + +#include "api.h" + +#include + +#include +#include + +PXR_NAMESPACE_OPEN_SCOPE + +class CPVColor : public MPxNode +{ +public: + PXRUSDPREVIEWSURFACE_API + static void* creator(); + + PXRUSDPREVIEWSURFACE_API + CPVColor(); + + PXRUSDPREVIEWSURFACE_API + ~CPVColor() override; + + PXRUSDPREVIEWSURFACE_API + static MStatus initialize(); + + PXRUSDPREVIEWSURFACE_API + SchedulingType schedulingType() const override; + + PXRUSDPREVIEWSURFACE_API + static MStatus initialize(); + + PXRUSDPREVIEWSURFACE_API + static const MTypeId id; + +private: + static MObject aUVCoord; + + static MObject aOutColor; + + static MObject aOutAlpha; +}; + +class CPVColorShadingNodeOverride : public MHWRender::MPxShadingNodeOverride +{ +public: + PXRUSDPREVIEWSURFACE_API + static MHWRender::MPxShadingNodeOverride* creator(const MObject& obj); + + PXRUSDPREVIEWSURFACE_API + ~CPVColorShadingNodeOverride() override; + + PXRUSDPREVIEWSURFACE_API + MHWRender::DrawAPI supportedDrawAPIs() const override; + + PXRUSDPREVIEWSURFACE_API + MString fragmentName() const override; + +private: + CPVColorShadingNodeOverride(const MObject& obj); +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp index e70c47b1a5..05366015ec 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp @@ -76,7 +76,6 @@ MStatus PxrMayaUsdPreviewSurface::initialize() MObject opacityThresholdAttr; MObject roughnessAttr; MObject specularColorAttr; - MObject displayCPVAttr; MObject useSpecularWorkflowAttr; MObject outColorAttr; MObject outTransparencyAttr; @@ -291,18 +290,6 @@ MStatus PxrMayaUsdPreviewSurface::initialize() status = addAttribute(specularColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); - displayCPVAttr = numericAttrFn.create( - PxrMayaUsdPreviewSurfaceTokens->DisplayCPVAttrName.GetText(), - "cpv", - MFnNumericData::kBoolean, - 0.0, - &status); - CHECK_MSTATUS_AND_RETURN_IT(status); - status = numericAttrFn.setAffectsAppearance(true); - CHECK_MSTATUS_AND_RETURN_IT(status); - status = addAttribute(displayCPVAttr); - CHECK_MSTATUS_AND_RETURN_IT(status); - useSpecularWorkflowAttr = numericAttrFn.create( PxrMayaUsdPreviewSurfaceTokens->UseSpecularWorkflowAttrName.GetText(), "usw", @@ -396,8 +383,6 @@ MStatus PxrMayaUsdPreviewSurface::initialize() CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(specularColorAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); - status = attributeAffects(displayCPVAttr, outColorAttr); - CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(useSpecularWorkflowAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h index 6d6b0357a1..1d4d45b121 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h @@ -48,7 +48,6 @@ PXR_NAMESPACE_OPEN_SCOPE ((OpacityThresholdAttrName, "opacityThreshold")) \ ((RoughnessAttrName, "roughness")) \ ((SpecularColorAttrName, "specularColor")) \ - ((DisplayCPVAttrName, "displayCPV")) \ ((UseSpecularWorkflowAttrName, "useSpecularWorkflow")) \ ((OutColorAttrName, "outColor")) \ ((OutTransparencyAttrName, "outTransparency")) \ diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp index 2bd33511b1..f772846b59 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp @@ -15,9 +15,9 @@ // #include "usdPreviewSurfacePlugin.h" +#include "cpvColor.h" #include "usdPreviewSurface.h" #include "usdPreviewSurfaceReader.h" -#include "usdPreviewSurfaceShaderOverride.h" #include "usdPreviewSurfaceShadingNodeOverride.h" #include "usdPreviewSurfaceWriter.h" @@ -37,8 +37,10 @@ PXR_NAMESPACE_OPEN_SCOPE namespace { -TfToken::Set _registeredTypeNames; -static constexpr char shaderOverrideIdSuffix[] = "ShaderOverride"; +TfToken::Set _registeredTypeNames; +static const MString cpvColorShaderName("cpvColor"); +static const MString cpvColorShaderUserClassification("texture/2d:"); +static const MString cpvColorShaderDrawClassification("drawdb/shader/texture/2d/"); } // namespace /* static */ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( @@ -73,10 +75,22 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( drawDbClassification, registrantId, PxrMayaUsdPreviewSurfaceShadingNodeOverride::creator); CHECK_MSTATUS(status); - status = MHWRender::MDrawRegistry::registerShaderOverrideCreator( - drawDbClassification, - registrantId + shaderOverrideIdSuffix, - PxrMayaUsdPreviewSurfaceShaderOverride::creator); + // Register CPV shader node + const MString cpvDrawClassify(cpvColorShaderDrawClassification + cpvColorShaderName); + MString cpvUserClassify(cpvColorShaderUserClassification); + cpvUserClassify += cpvDrawClassify; + + status = plugin.registerNode( + cpvColorShaderName, + CPVColor::id, + CPVColor::creator, + CPVColor::initialize, + MPxNode::kDependNode, + &cpvUserClassify); + CHECK_MSTATUS(status); + + status = MHWRender::MDrawRegistry::registerShadingNodeOverrideCreator( + cpvDrawClassify, registrantId, CPVColorShadingNodeOverride::creator); CHECK_MSTATUS(status); return status; @@ -101,8 +115,11 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::finalize( deregisterFragments(); - MStatus status = MHWRender::MDrawRegistry::deregisterShaderOverrideCreator( - drawDbClassification, registrantId + shaderOverrideIdSuffix); + const MString cpvDrawClassify(cpvColorShaderDrawClassification + cpvColorShaderName); + MStatus status = plugin.deregisterNode(CPVColor::id); + CHECK_MSTATUS(status); + status = MHWRender::MDrawRegistry::deregisterShadingNodeOverrideCreator( + cpvDrawClassify, registrantId); CHECK_MSTATUS(status); status = MHWRender::MDrawRegistry::deregisterSurfaceShadingNodeOverrideCreator( diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp deleted file mode 100644 index c67054c1e0..0000000000 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// -// Copyright 2021 Animal Logic -// -// 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 "usdPreviewSurfaceShaderOverride.h" - -#include "usdPreviewSurfacePlugin.h" - -#include - -#include - -#include -#include - -PXR_NAMESPACE_OPEN_SCOPE - -static MStatus populateShaderManager(const MShaderManager* shaderMgr) -{ - MRenderer* renderer = MRenderer::theRenderer(); - if (renderer) { - shaderMgr = renderer->getShaderManager(); - if (shaderMgr) - return MS::kSuccess; - } - TF_RUNTIME_ERROR("Failed to populate shader manager."); - return MS::kFailure; -} - -inline static MShaderInstance* getPreviewSurfaceShader(const MShaderManager* shaderMgr) -{ - return shaderMgr->getFragmentShader( - HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText(), "outSurfaceFinal", true); -} - -inline static MShaderInstance* -cloneOrCreateInstance(const MShaderManager* shaderMgr, MShaderInstance* instance) -{ - // Clone the shader instance or create a new one - return instance ? instance->clone() : getPreviewSurfaceShader(shaderMgr); -} - -MPxShaderOverride* PxrMayaUsdPreviewSurfaceShaderOverride::creator(const MObject& obj) -{ - // Make sure the shader fragments have been registered before instantiating the override - PxrMayaUsdPreviewSurfacePlugin::registerFragments(); - return new PxrMayaUsdPreviewSurfaceShaderOverride(obj); -} - -PxrMayaUsdPreviewSurfaceShaderOverride::PxrMayaUsdPreviewSurfaceShaderOverride(const MObject& obj) - : MPxShaderOverride(obj) -{ -} - -PxrMayaUsdPreviewSurfaceShaderOverride::~PxrMayaUsdPreviewSurfaceShaderOverride() -{ - // Release and clear all held shader instances - const MShaderManager* shaderMgr = nullptr; - if (populateShaderManager(shaderMgr)) { - if (m_shaderInstanceNonTextured) { - shaderMgr->releaseShader(m_shaderInstanceNonTextured); - m_shaderInstanceNonTextured = nullptr; - } - if (m_shaderInstance) { - shaderMgr->releaseShader(m_shaderInstance); - m_shaderInstance = nullptr; - } - } -} - -MHWRender::DrawAPI PxrMayaUsdPreviewSurfaceShaderOverride::supportedDrawAPIs() const -{ - return MHWRender::kAllDevices; -} - -bool PxrMayaUsdPreviewSurfaceShaderOverride::rebuildAlways() { return true; } - -#if MAYA_API_VERSION >= 20220000 -MString PxrMayaUsdPreviewSurfaceShaderOverride::initialize( - const MInitContext& initContext, - MSharedPtr& data) -#else -MString PxrMayaUsdPreviewSurfaceShaderOverride::initialize( - const MInitContext& initContext, - MInitFeedback& data) -#endif -{ - // Define the geometry requirements for the mayaCPVInput fragment - addGeometryRequirement({ {}, MGeometry::kNormal, MGeometry::kFloat, 3 }); - addGeometryRequirement({ {}, MGeometry::kColor, MGeometry::kFloat, 4 }); - - // Create instances of the USD preview surface fragment shader - const MShaderManager* shaderMgr = nullptr; - if (populateShaderManager(shaderMgr)) { - if (!m_shaderInstanceNonTextured) - m_shaderInstanceNonTextured = getPreviewSurfaceShader(shaderMgr); - - if (!m_shaderInstance) { - m_shaderInstance = cloneOrCreateInstance(shaderMgr, m_shaderInstanceNonTextured); - } - } - return MPxShaderOverride::initialize(initContext, data); -} - -MShaderInstance* -PxrMayaUsdPreviewSurfaceShaderOverride::nonTexturedShaderInstance(bool& monitorNode) const -{ - monitorNode = true; // TODO why is this not running the update loop?? - return m_shaderInstanceNonTextured; -} - -void PxrMayaUsdPreviewSurfaceShaderOverride::updateDG(MObject obj) -{ - // Update the cached attributes for the node - MStatus status; - MFnDependencyNode node(obj, &status); - if (!status) - return; - - node.findPlug("diffuseColorR", true).getValue(m_diffuseColor[0]); - node.findPlug("diffuseColorG", true).getValue(m_diffuseColor[1]); - node.findPlug("diffuseColorB", true).getValue(m_diffuseColor[2]); - - node.findPlug("emissiveColorR", true).getValue(m_emissiveColor[0]); - node.findPlug("emissiveColorG", true).getValue(m_emissiveColor[1]); - node.findPlug("emissiveColorB", true).getValue(m_emissiveColor[2]); - - node.findPlug("occlusion", true).getValue(m_occlusion); - node.findPlug("opacity", true).getValue(m_opacity); - node.findPlug("opacityThreshold", true).getValue(m_opacityThreshold); - node.findPlug("ior", true).getValue(m_ior); - node.findPlug("metallic", true).getValue(m_metallic); - node.findPlug("roughness", true).getValue(m_roughness); - - node.findPlug("specularColorR", true).getValue(m_specularColor[0]); - node.findPlug("specularColorG", true).getValue(m_specularColor[1]); - node.findPlug("specularColorB", true).getValue(m_specularColor[2]); - - node.findPlug("clearcoat", true).getValue(m_clearcoat); - node.findPlug("clearcoatRoughness", true).getValue(m_clearcoatRoughness); - node.findPlug("displacement", true).getValue(m_displacement); - - node.findPlug("normal0", true).getValue(m_normal[0]); - node.findPlug("normal1", true).getValue(m_normal[1]); - node.findPlug("normal2", true).getValue(m_normal[2]); - - // Store previous display value - m_previousDisplayCPV = m_displayCPV; - node.findPlug("displayCPV", true).getValue(m_displayCPV); - node.findPlug("useSpecularWorkflow", true).getValue(m_useSpecularWorkflow); - node.findPlug("caching", true).getValue(m_caching); - node.findPlug("frozen", true).getValue(m_frozen); -} - -void PxrMayaUsdPreviewSurfaceShaderOverride::updateDevice() -{ - // Recreate the textured shader if the CPV display value changed or does not exist - const MShaderManager* shaderMgr = nullptr; - if ((m_displayCPV != m_previousDisplayCPV || !m_shaderInstance) - && populateShaderManager(shaderMgr)) { - if (m_shaderInstance) { - shaderMgr->releaseShader(m_shaderInstance); - m_shaderInstance = nullptr; - } - - // Rebuild the textured shader - m_shaderInstance = cloneOrCreateInstance(shaderMgr, m_shaderInstanceNonTextured); - if (!m_shaderInstance) - TF_RUNTIME_ERROR("Failed to recreate textured shader instance."); - } - - // Update the parameters for each shader instance - setShaderParams(m_shaderInstanceNonTextured); - setShaderParams(m_shaderInstance, m_displayCPV); -} - -void PxrMayaUsdPreviewSurfaceShaderOverride::setShaderParams( - MShaderInstance*& shaderInstance, - bool displayCVP) -{ - if (!shaderInstance) - return; - - if (displayCVP) { - // Set the CPV inputs to the shader instance - shaderInstance->addInputFragment("mayaCPVInput", "outColor", "diffuseColor"); - shaderInstance->addInputFragment("mayaCPVInput", "outTransparency", "dummyTransparency"); - shaderInstance->setIsTransparent(true); - } else { - shaderInstance->setParameter("diffuseColor", &m_diffuseColor[0]); - shaderInstance->setParameter("dummyTransparency", 0.f); - shaderInstance->setIsTransparent(false); - } - - // Copy the cached attributes from the node to the shader instance - shaderInstance->setParameter("emissiveColor", &m_emissiveColor[0]); - shaderInstance->setParameter("occlusion", m_occlusion); - shaderInstance->setParameter("opacity", m_opacity); - shaderInstance->setParameter("opacityThreshold", m_opacityThreshold); - shaderInstance->setParameter("ior", m_ior); - shaderInstance->setParameter("metallic", m_metallic); - shaderInstance->setParameter("roughness", m_roughness); - shaderInstance->setParameter("specularColor", &m_specularColor[0]); - shaderInstance->setParameter("clearcoat", m_clearcoat); - shaderInstance->setParameter("clearcoatRoughness", m_clearcoatRoughness); - shaderInstance->setParameter("displacement", m_displacement); - shaderInstance->setParameter("normal", &m_normal[0]); - shaderInstance->setParameter("useSpecularWorkflow", m_useSpecularWorkflow); - shaderInstance->setParameter("caching", m_caching); - shaderInstance->setParameter("frozen", m_frozen); -} - -bool PxrMayaUsdPreviewSurfaceShaderOverride::handlesDraw(MDrawContext& context) -{ - // Handle draw on non-overriden color passes - const MPassContext& passCtx = context.getPassContext(); - const MStringArray& passSemantics = passCtx.passSemantics(); - for (const MString& semantic : passSemantics) { - if (semantic == MPassContext::kColorPassSemantic && !passCtx.hasShaderOverride()) { - return true; - } - } - return false; -} - -MShaderInstance* PxrMayaUsdPreviewSurfaceShaderOverride::shaderInstance(MDrawContext& context) const -{ - return m_shaderInstance; -} - -void PxrMayaUsdPreviewSurfaceShaderOverride::activateKey(MDrawContext& context, const MString& key) -{ - if (!m_shaderInstance) - return; - m_shaderInstance->updateParameters(context); - m_shaderInstance->bind(context); -} - -bool PxrMayaUsdPreviewSurfaceShaderOverride::draw( - MDrawContext& context, - const MRenderItemList& renderItemList) const -{ - if (m_shaderInstance) { - const unsigned int passCount = m_shaderInstance->getPassCount(context); - for (unsigned int i = 0; i < passCount; i++) { - m_shaderInstance->activatePass(context, i); - MPxShaderOverride::drawGeometry(context); - } - } - return true; -} - -void PxrMayaUsdPreviewSurfaceShaderOverride::terminateKey(MDrawContext& context, const MString& key) -{ - if (m_shaderInstance) - m_shaderInstance->unbind(context); -} - -PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h deleted file mode 100644 index 8f18c4cb15..0000000000 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceShaderOverride.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2021 Animal Logic -// -// 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 PXRUSDPREVIEWSURFACE_USD_PREVIEW_SURFACE_SHADER_OVERRIDE_H -#define PXRUSDPREVIEWSURFACE_USD_PREVIEW_SURFACE_SHADER_OVERRIDE_H - -#include "api.h" - -#include - -#include -#include - -PXR_NAMESPACE_OPEN_SCOPE - -class PxrMayaUsdPreviewSurfaceShaderOverride : public MPxShaderOverride -{ -public: - PXRUSDPREVIEWSURFACE_API - static MPxShaderOverride* creator(const MObject& obj); - - PXRUSDPREVIEWSURFACE_API - ~PxrMayaUsdPreviewSurfaceShaderOverride() override; - - PXRUSDPREVIEWSURFACE_API - MHWRender::DrawAPI supportedDrawAPIs() const override; - - PXRUSDPREVIEWSURFACE_API - bool rebuildAlways() override; - - PXRUSDPREVIEWSURFACE_API -#if MAYA_API_VERSION >= 20220000 - MString initialize(const MInitContext& initContext, MSharedPtr& userData) override; -#else - MString initialize(const MInitContext& initContext, MInitFeedback& initFeedback) override; -#endif - - PXRUSDPREVIEWSURFACE_API - MShaderInstance* nonTexturedShaderInstance(bool& monitorNode) const override; - - PXRUSDPREVIEWSURFACE_API - void updateDG(MObject obj) override; - - PXRUSDPREVIEWSURFACE_API - void updateDevice() override; - - PXRUSDPREVIEWSURFACE_API - bool handlesDraw(MDrawContext& context) override; - - PXRUSDPREVIEWSURFACE_API - MShaderInstance* shaderInstance(MDrawContext& context) const override; - - PXRUSDPREVIEWSURFACE_API - void activateKey(MDrawContext& context, const MString& key) override; - - PXRUSDPREVIEWSURFACE_API - bool draw(MDrawContext& context, const MRenderItemList& renderItemList) const override; - - PXRUSDPREVIEWSURFACE_API - void terminateKey(MDrawContext& context, const MString& key) override; - -private: - PxrMayaUsdPreviewSurfaceShaderOverride(const MObject& obj); - - void setShaderParams(MShaderInstance*& shaderInstance, bool displayCVP = false); - - MShaderInstance* m_shaderInstance = nullptr; - - MShaderInstance* m_shaderInstanceNonTextured = nullptr; - - float m_diffuseColor[3]; - float m_emissiveColor[3]; - float m_occlusion; - float m_opacity; - float m_opacityThreshold; - float m_ior; - float m_metallic; - float m_roughness; - float m_specularColor[3]; - float m_clearcoat; - float m_clearcoatRoughness; - float m_displacement; - float m_normal[3]; - bool m_useSpecularWorkflow; - bool m_caching; - bool m_frozen; - bool m_displayCPV; - bool m_previousDisplayCPV; -}; - -PXR_NAMESPACE_CLOSE_SCOPE - -#endif From 384a4c969af822988de59c1f78405734a1c6ebd0 Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Tue, 18 Jan 2022 17:31:16 +1100 Subject: [PATCH 5/7] Added opacity attribute to CPVColor shading node --- lib/usd/pxrUsdPreviewSurface/cpvColor.cpp | 44 +++++++++++++------ lib/usd/pxrUsdPreviewSurface/cpvColor.h | 15 +++++-- .../usdPreviewSurfacePlugin.cpp | 14 +++--- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp b/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp index 87ea829565..b63a4924a7 100644 --- a/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp +++ b/lib/usd/pxrUsdPreviewSurface/cpvColor.cpp @@ -22,10 +22,14 @@ PXR_NAMESPACE_OPEN_SCOPE static const MString cpvInputFragmentName("mayaCPVInput"); +const MString CPVColor::name("cpvColor"); +const MString CPVColor::userClassification("utility/color:"); +const MString CPVColor::drawClassification("drawdb/shader/utility/color/"); + const MTypeId CPVColor::id(0x58000098); -MObject CPVColor::aUVCoord; MObject CPVColor::aOutColor; MObject CPVColor::aOutAlpha; +MObject CPVColor::aOutOpacity; void* CPVColor::creator() { return new CPVColor(); } @@ -37,14 +41,6 @@ MStatus CPVColor::initialize() { // Define implicit shading network attributes MFnNumericAttribute nAttr; - MObject uCoord = nAttr.create("uCoord", "u", MFnNumericData::kFloat); - MObject vCoord = nAttr.create("vCoord", "v", MFnNumericData::kFloat); - aUVCoord = nAttr.create("uvCoord", "uv", uCoord, vCoord); - CHECK_MSTATUS(nAttr.setKeyable(true)); - CHECK_MSTATUS(nAttr.setStorable(true)); - CHECK_MSTATUS(nAttr.setReadable(true)); - CHECK_MSTATUS(nAttr.setWritable(true)); - CHECK_MSTATUS(nAttr.setHidden(true)); aOutColor = nAttr.createColor("outColor", "oc"); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setStorable(false)); @@ -55,15 +51,37 @@ MStatus CPVColor::initialize() CHECK_MSTATUS(nAttr.setStorable(false)); CHECK_MSTATUS(nAttr.setReadable(true)); CHECK_MSTATUS(nAttr.setWritable(false)); + CHECK_MSTATUS(nAttr.setHidden(true)); + aOutOpacity = nAttr.create("outOpacity", "oo", MFnNumericData::kFloat); + CHECK_MSTATUS(nAttr.setKeyable(false)); + CHECK_MSTATUS(nAttr.setStorable(false)); + CHECK_MSTATUS(nAttr.setReadable(true)); + CHECK_MSTATUS(nAttr.setWritable(false)); - // Add attributes and setup attribute affecting relationships - CHECK_MSTATUS(addAttribute(aUVCoord)); + // Add attributes CHECK_MSTATUS(addAttribute(aOutColor)); CHECK_MSTATUS(addAttribute(aOutAlpha)); - CHECK_MSTATUS(attributeAffects(aUVCoord, aOutColor)); - CHECK_MSTATUS(attributeAffects(aUVCoord, aOutAlpha)); + CHECK_MSTATUS(addAttribute(aOutOpacity)); + + return MS::kSuccess; +} MPxNode::SchedulingType CPVColor::schedulingType() const { return SchedulingType::kParallel; } + +MStatus CPVColor::compute(const MPlug& plug, MDataBlock& block) +{ + if ((plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha) + && (plug != aOutOpacity)) + return MS::kUnknownParameter; + + // Complement alpha for opacity attribute + MDataHandle outAlphaHandle = block.outputValue(aOutAlpha); + MDataHandle outOpacityHandle = block.outputValue(aOutOpacity); + float& outOpacity = outOpacityHandle.asFloat(); + outOpacity = 1 - outAlphaHandle.asFloat(); + outOpacityHandle.setClean(); + outAlphaHandle.setClean(); + return MS::kSuccess; } diff --git a/lib/usd/pxrUsdPreviewSurface/cpvColor.h b/lib/usd/pxrUsdPreviewSurface/cpvColor.h index cb6b440cb4..cfc26f7694 100644 --- a/lib/usd/pxrUsdPreviewSurface/cpvColor.h +++ b/lib/usd/pxrUsdPreviewSurface/cpvColor.h @@ -29,6 +29,15 @@ PXR_NAMESPACE_OPEN_SCOPE class CPVColor : public MPxNode { public: + PXRUSDPREVIEWSURFACE_API + static const MString name; + + PXRUSDPREVIEWSURFACE_API + static const MString userClassification; + + PXRUSDPREVIEWSURFACE_API + static const MString drawClassification; + PXRUSDPREVIEWSURFACE_API static void* creator(); @@ -45,17 +54,17 @@ class CPVColor : public MPxNode SchedulingType schedulingType() const override; PXRUSDPREVIEWSURFACE_API - static MStatus initialize(); + MStatus compute(const MPlug& plug, MDataBlock& block) override; PXRUSDPREVIEWSURFACE_API static const MTypeId id; private: - static MObject aUVCoord; - static MObject aOutColor; static MObject aOutAlpha; + + static MObject aOutOpacity; }; class CPVColorShadingNodeOverride : public MHWRender::MPxShadingNodeOverride diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp index f772846b59..fc1d4ec021 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfacePlugin.cpp @@ -37,10 +37,7 @@ PXR_NAMESPACE_OPEN_SCOPE namespace { -TfToken::Set _registeredTypeNames; -static const MString cpvColorShaderName("cpvColor"); -static const MString cpvColorShaderUserClassification("texture/2d:"); -static const MString cpvColorShaderDrawClassification("drawdb/shader/texture/2d/"); +TfToken::Set _registeredTypeNames; } // namespace /* static */ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( @@ -76,12 +73,12 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::initialize( CHECK_MSTATUS(status); // Register CPV shader node - const MString cpvDrawClassify(cpvColorShaderDrawClassification + cpvColorShaderName); - MString cpvUserClassify(cpvColorShaderUserClassification); + const MString cpvDrawClassify(CPVColor::drawClassification + CPVColor::name); + MString cpvUserClassify(CPVColor::userClassification); cpvUserClassify += cpvDrawClassify; status = plugin.registerNode( - cpvColorShaderName, + CPVColor::name, CPVColor::id, CPVColor::creator, CPVColor::initialize, @@ -115,11 +112,10 @@ MStatus PxrMayaUsdPreviewSurfacePlugin::finalize( deregisterFragments(); - const MString cpvDrawClassify(cpvColorShaderDrawClassification + cpvColorShaderName); MStatus status = plugin.deregisterNode(CPVColor::id); CHECK_MSTATUS(status); status = MHWRender::MDrawRegistry::deregisterShadingNodeOverrideCreator( - cpvDrawClassify, registrantId); + CPVColor::drawClassification + CPVColor::name, registrantId); CHECK_MSTATUS(status); status = MHWRender::MDrawRegistry::deregisterSurfaceShadingNodeOverrideCreator( From 98790a41d29aac0a9ebd6a16ada28e7c82e7c960 Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Thu, 27 Jan 2022 14:07:56 +1100 Subject: [PATCH 6/7] Added test for importing USD preview surface with displayColor shader --- .../baseline/DisplayColorCube.png | Bin 0 -> 50668 bytes .../testVP2RenderDelegateUSDPreviewSurface.py | 24 +++++++ .../UsdPreviewSurface/DisplayColorCube.usda | 59 ++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/DisplayColorCube.png create mode 100644 test/testSamples/UsdPreviewSurface/DisplayColorCube.usda diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/DisplayColorCube.png b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/DisplayColorCube.png new file mode 100644 index 0000000000000000000000000000000000000000..c51a0b6b544b24b96f8aabbb0ea251fa0aad1d86 GIT binary patch literal 50668 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 HWAOh2>{g)2 literal 0 HcmV?d00001 diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py index c9ef8395ad..3f04ae7ebe 100644 --- a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py +++ b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py @@ -206,6 +206,30 @@ def testFallbackColor(self): self.assertSnapshotClose('TestFallbackColor.png') + def testImportDisplayColor(self): + """Tests that the import of the USD preview surface containing a connected displayColor + primvar reader shader node is imported with vertex colours for textured display""" + cmds.file(force=True, new=True) + mayaUtils.loadPlugin("mayaUsdPlugin") + + # Turn on textured display and focus in on the subject + panel = mayaUtils.activeModelPanel() + cmds.modelEditor(panel, e=1, displayTextures=1) + cmds.dolly("persp", abs=True, d=3.2) + + # Import the USD file + testFile = testUtils.getTestScene("UsdPreviewSurface", "DisplayColorCube.usda") + options = ["shadingMode=[[useRegistry,UsdPreviewSurface]]", + "primPath=/", + "preferredMaterial=none"] + cmds.file(testFile, i=True, type="USD Import", + ignoreVersion=True, ra=True, mergeNamespacesOnClash=False, + namespace="Test", pr=True, importTimeRange="combine", + options=";".join(options)) + + # Snapshot and assert similarity + self.assertSnapshotClose('DisplayColorCube.png') + if __name__ == '__main__': fixturesUtils.runTests(globals()) diff --git a/test/testSamples/UsdPreviewSurface/DisplayColorCube.usda b/test/testSamples/UsdPreviewSurface/DisplayColorCube.usda new file mode 100644 index 0000000000..aa43087a1d --- /dev/null +++ b/test/testSamples/UsdPreviewSurface/DisplayColorCube.usda @@ -0,0 +1,59 @@ +#usda 1.0 +( + defaultPrim = "DisplayColorCube" + endTimeCode = 120 + startTimeCode = 1 +) + +def Mesh "DisplayColorCube" +{ + float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)] + int[] faceVertexCounts = [4, 4, 4, 4, 4, 4] + int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, 1, 7, 5, 3, 6, 0, 2, 4] + normal3f[] normals = [(-0.5773503, -0.5773503, 0.5773503), (0.5773503, -0.5773503, 0.5773503), (-0.5773503, 0.5773503, 0.5773503), (0.5773503, 0.5773503, 0.5773503), (-0.5773503, 0.5773503, -0.5773503), (0.5773503, 0.5773503, -0.5773503), (-0.5773503, -0.5773503, -0.5773503), (0.5773503, -0.5773503, -0.5773503)] ( + interpolation = "vertex" + ) + point3f[] points = [(-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5)] + color3f[] primvars:displayColor = [(0.08660001, 0.8203, 0.080200024), (0.8203, 0.7824, 0.080200024), (0.7843, 0.07679997, 0.07679997), (0, 0, 0), (0.8203, 0.080200024, 0.59370005), (0.080200024, 0.17610006, 0.8203), (0.7843, 0.07679997, 0.07679997), (0.080200024, 0.8203, 0.70350003)] ( + interpolation = "vertex" + ) + float[] primvars:displayOpacity = [1, 1, 1, 1, 1, 1, 1, 1] ( + interpolation = "vertex" + ) + float2[] primvars:st = [(0.375, 0), (0.625, 0), (0.375, 0.25), (0.625, 0.25), (0.375, 0.5), (0.625, 0.5), (0.375, 0.75), (0.625, 0.75), (0.375, 1), (0.625, 1), (0.875, 0), (0.875, 0.25), (0.125, 0), (0.125, 0.25)] ( + interpolation = "faceVarying" + ) + int[] primvars:st:indices = [0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 9, 8, 1, 10, 11, 3, 12, 0, 2, 13] + uniform token[] xformOpOrder = [] + rel material:binding = + + def Scope "Looks" + { + def Material "usdPreviewSurface1SG" + { + token outputs:surface.connect = + + def Shader "usdPreviewSurface1" + { + uniform token info:id = "UsdPreviewSurface" + color3f inputs:diffuseColor.connect = + token outputs:displacement + token outputs:surface + } + + def Shader "Primvar" + { + uniform token info:id = "UsdPrimvarReader_float2" + string inputs:varname.connect = + float2 outputs:result + } + + def Shader "ColorPrimvar" + { + uniform token info:id = "UsdPrimvarReader_float3" + string inputs:varname = "displayColor" + float3 outputs:result + } + } + } +} From 351dd6192a379b81bea873e7ded64e6b10e55e95 Mon Sep 17 00:00:00 2001 From: Jonathan Moallem Date: Tue, 18 Jan 2022 17:33:55 +1100 Subject: [PATCH 7/7] Added PrimvarReader_float3 translation for displayColor --- lib/usd/translators/shading/CMakeLists.txt | 1 + lib/usd/translators/shading/shadingTokens.cpp | 2 +- lib/usd/translators/shading/shadingTokens.h | 6 +- .../shading/usdPrimvarReaderFloat3Reader.cpp | 97 +++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 lib/usd/translators/shading/usdPrimvarReaderFloat3Reader.cpp diff --git a/lib/usd/translators/shading/CMakeLists.txt b/lib/usd/translators/shading/CMakeLists.txt index 54a64d248b..d3ca2fbede 100644 --- a/lib/usd/translators/shading/CMakeLists.txt +++ b/lib/usd/translators/shading/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(${TARGET_NAME} usdPhongEWriter.cpp usdReflectWriter.cpp usdUVTextureReader.cpp + usdPrimvarReaderFloat3Reader.cpp ) if (BUILD_RFM_TRANSLATORS) diff --git a/lib/usd/translators/shading/shadingTokens.cpp b/lib/usd/translators/shading/shadingTokens.cpp index 91dfd64128..a57f858698 100644 --- a/lib/usd/translators/shading/shadingTokens.cpp +++ b/lib/usd/translators/shading/shadingTokens.cpp @@ -21,7 +21,7 @@ TF_DEFINE_PUBLIC_TOKENS(TrUsdTokens, TR_USD_COMMON TR_USD_TEXTURE TR_USD_PRIMVAR TF_DEFINE_PUBLIC_TOKENS( TrMayaTokens, - TR_MAYA_MATERIALS TR_MAYA_STANDARD_SURFACE TR_MAYA_FILE TR_MAYA_UV); + TR_MAYA_MATERIALS TR_MAYA_STANDARD_SURFACE TR_MAYA_FILE TR_MAYA_UV TR_MAYA_PRIMVAR); #ifdef WANT_MATERIALX_TRANSLATORS TF_DEFINE_PUBLIC_TOKENS( diff --git a/lib/usd/translators/shading/shadingTokens.h b/lib/usd/translators/shading/shadingTokens.h index ebd83e27a1..ec2fa7b44a 100644 --- a/lib/usd/translators/shading/shadingTokens.h +++ b/lib/usd/translators/shading/shadingTokens.h @@ -52,6 +52,7 @@ PXR_NAMESPACE_OPEN_SCOPE #define TR_USD_PRIMVAR \ (UsdPrimvarReader_float2) \ + (displayColor) \ (result) #define TR_USD_XFORM \ @@ -173,12 +174,15 @@ TF_DECLARE_PUBLIC_TOKENS(TrUsdTokens, , TR_USD_COMMON TR_USD_TEXTURE TR_USD_PRIM (outUV) \ (uvCoord) +#define TR_MAYA_PRIMVAR \ + (cpvColor) + // clang-format on TF_DECLARE_PUBLIC_TOKENS( TrMayaTokens, , - TR_MAYA_MATERIALS TR_MAYA_STANDARD_SURFACE TR_MAYA_FILE TR_MAYA_UV); + TR_MAYA_MATERIALS TR_MAYA_STANDARD_SURFACE TR_MAYA_FILE TR_MAYA_UV TR_MAYA_PRIMVAR); #ifdef WANT_MATERIALX_TRANSLATORS diff --git a/lib/usd/translators/shading/usdPrimvarReaderFloat3Reader.cpp b/lib/usd/translators/shading/usdPrimvarReaderFloat3Reader.cpp new file mode 100644 index 0000000000..e99878c480 --- /dev/null +++ b/lib/usd/translators/shading/usdPrimvarReaderFloat3Reader.cpp @@ -0,0 +1,97 @@ +// +// Copyright 2021 Animal Logic +// +// 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 "shadingTokens.h" + +#include +#include + +#include + +#include + +PXR_NAMESPACE_OPEN_SCOPE + +class PxrMayaUsdPrimvarReader_float3_Reader : public UsdMayaShaderReader +{ +public: + PxrMayaUsdPrimvarReader_float3_Reader(const UsdMayaPrimReaderArgs& readArgs); + + bool Read(UsdMayaPrimReaderContext& context) override; + + TfToken GetMayaNameForUsdAttrName(const TfToken& usdAttrName) const override; +}; + +PXRUSDMAYA_REGISTER_SHADER_READER(UsdPrimvarReader_float3, PxrMayaUsdPrimvarReader_float3_Reader) + +PxrMayaUsdPrimvarReader_float3_Reader::PxrMayaUsdPrimvarReader_float3_Reader( + const UsdMayaPrimReaderArgs& readArgs) + : UsdMayaShaderReader(readArgs) +{ +} + +/* virtual */ +bool PxrMayaUsdPrimvarReader_float3_Reader::Read(UsdMayaPrimReaderContext& context) +{ + const UsdPrim& prim = _GetArgs().GetUsdPrim(); + UsdShadeShader shaderSchema = UsdShadeShader(prim); + if (!shaderSchema) { + return false; + } + + MObject obj; + VtValue val; + UsdShadeInput usdInput = shaderSchema.GetInput(TrUsdTokens->varname); + if (usdInput && usdInput.Get(&val) && val.IsHolding() + && val.UncheckedGet() == TrUsdTokens->displayColor.GetString()) { + // Create a CPV color node in place of USD's displayColor primvar reader + MStatus status; + MFnDependencyNode depFn; + obj = depFn.create(TrMayaTokens->cpvColor.GetText(), &status); + if (status != MS::kSuccess) { + TF_RUNTIME_ERROR( + "Could not create node of type %s for prim '%s'. ", + TrMayaTokens->cpvColor.GetText(), + prim.GetPath().GetText()); + return false; + } + } + + if (obj.isNull()) { + return false; + } + + context.RegisterNewMayaNode(prim.GetPath().GetString(), obj); + return true; +} + +/* virtual */ +TfToken +PxrMayaUsdPrimvarReader_float3_Reader::GetMayaNameForUsdAttrName(const TfToken& usdAttrName) const +{ + TfToken baseName; + UsdShadeAttributeType attrType; + std::tie(baseName, attrType) = UsdShadeUtils::GetBaseNameAndType(usdAttrName); + + if (attrType == UsdShadeAttributeType::Output) { + if (baseName == TrUsdTokens->result) { + return TrMayaTokens->outColor; + } + } + return TfToken(); +} + +PXR_NAMESPACE_CLOSE_SCOPE \ No newline at end of file