From 78e8633732fb3bffe738e2337cfe2d93c17f1c5c Mon Sep 17 00:00:00 2001 From: Dhruv Govil Date: Wed, 11 Nov 2020 13:45:13 -0800 Subject: [PATCH] Add Opacity Threshold Attribute to USD Preview Shader --- .../AEusdPreviewSurfaceTemplate.mel | 1 + .../usdPreviewSurface.cpp | 36 +++++++++- .../pxrUsdPreviewSurface/usdPreviewSurface.h | 3 + .../usdPreviewSurfaceWriter.cpp | 9 +++ test/lib/usd/translators/CMakeLists.txt | 1 + .../translators/testUsdExportPreviewShader.py | 69 +++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 test/lib/usd/translators/testUsdExportPreviewShader.py diff --git a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel index 0435acd8a8..b207ce6324 100644 --- a/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel +++ b/lib/usd/pxrUsdPreviewSurface/AEusdPreviewSurfaceTemplate.mel @@ -41,6 +41,7 @@ global proc AE${PREVIEWSURFACE_MAYA_TYPE_NAME}Template(string $nodeName) editorTemplate -addControl "emissiveColor"; editorTemplate -addControl "occlusion"; editorTemplate -addControl "opacity"; + editorTemplate -addControl "opacityThreshold"; editorTemplate -beginLayout "Specular" -collapse false; editorTemplate -addControl "useSpecularWorkflow" diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp index 91892f1328..2c4bce7654 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.cpp @@ -42,6 +42,9 @@ TF_DEFINE_PUBLIC_TOKENS( PxrMayaUsdPreviewSurfaceTokens, PXRUSDPREVIEWSURFACE_USD_PREVIEW_SURFACE_TOKENS); +// Attributes +MObject PxrMayaUsdPreviewSurface::opacityThresholdAttr; + /* static */ void* PxrMayaUsdPreviewSurface::creator() { return new PxrMayaUsdPreviewSurface(); } @@ -228,6 +231,24 @@ MStatus PxrMayaUsdPreviewSurface::initialize() status = addAttribute(opacityAttr); CHECK_MSTATUS_AND_RETURN_IT(status); + opacityThresholdAttr = numericAttrFn.create( + PxrMayaUsdPreviewSurfaceTokens->OpacityThresholdAttrName.GetText(), + "opt", + MFnNumericData::kFloat, + 0.0, + &status); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = numericAttrFn.setSoftMin(0.0); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = numericAttrFn.setSoftMax(1.0); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = numericAttrFn.setKeyable(true); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = numericAttrFn.setAffectsAppearance(true); + CHECK_MSTATUS_AND_RETURN_IT(status); + status = addAttribute(opacityThresholdAttr); + CHECK_MSTATUS_AND_RETURN_IT(status); + roughnessAttr = numericAttrFn.create( PxrMayaUsdPreviewSurfaceTokens->RoughnessAttrName.GetText(), "rgh", @@ -345,6 +366,8 @@ MStatus PxrMayaUsdPreviewSurface::initialize() CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(opacityAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); + status = attributeAffects(opacityThresholdAttr, outColorAttr); + CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(roughnessAttr, outColorAttr); CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(specularColorAttr, outColorAttr); @@ -354,6 +377,8 @@ MStatus PxrMayaUsdPreviewSurface::initialize() status = attributeAffects(opacityAttr, outTransparencyAttr); CHECK_MSTATUS_AND_RETURN_IT(status); + status = attributeAffects(opacityThresholdAttr, outTransparencyAttr); + CHECK_MSTATUS_AND_RETURN_IT(status); status = attributeAffects(opacityAttr, outTransparencyOnAttr); CHECK_MSTATUS_AND_RETURN_IT(status); @@ -399,7 +424,16 @@ MStatus PxrMayaUsdPreviewSurface::compute(const MPlug& plug, MDataBlock& dataBlo = depNodeFn.attribute(PxrMayaUsdPreviewSurfaceTokens->OpacityAttrName.GetText()); const MDataHandle opacityData = dataBlock.inputValue(opacityAttr, &status); CHECK_MSTATUS(status); - const float opacity = opacityData.asFloat(); + float opacity = opacityData.asFloat(); + + const MDataHandle opacityThresholdData + = dataBlock.inputValue(opacityThresholdAttr, &status); + CHECK_MSTATUS(status); + const float opacityThreshold = opacityThresholdData.asFloat(); + + if (opacity <= opacityThreshold) { + opacity = 0.0f; + } const float transparency = 1.0f - opacity; const MFloatVector transparencyColor(transparency, transparency, transparency); diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h index 7aaf583b6a..1f08a9ff77 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurface.h @@ -45,6 +45,7 @@ PXR_NAMESPACE_OPEN_SCOPE ((NormalAttrName, "normal")) \ ((OcclusionAttrName, "occlusion")) \ ((OpacityAttrName, "opacity")) \ + ((OpacityThresholdAttrName, "opacityThreshold")) \ ((RoughnessAttrName, "roughness")) \ ((SpecularColorAttrName, "specularColor")) \ ((UseSpecularWorkflowAttrName, "useSpecularWorkflow")) \ @@ -76,6 +77,8 @@ class PxrMayaUsdPreviewSurface : public MPxNode PXRUSDPREVIEWSURFACE_API MStatus compute(const MPlug& plug, MDataBlock& dataBlock) override; + static MObject opacityThresholdAttr; + private: PxrMayaUsdPreviewSurface(); ~PxrMayaUsdPreviewSurface() override; diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp index ec4bab7ce5..82c72763b3 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp @@ -253,6 +253,14 @@ void PxrMayaUsdPreviewSurface_Writer::Write(const UsdTimeCode& usdTime) SdfValueTypeNames->Float, usdTime); + // Opacity Threshold + _AuthorShaderInputFromShadingNodeAttr( + depNodeFn, + shaderSchema, + PxrMayaUsdPreviewSurfaceTokens->OpacityThresholdAttrName, + SdfValueTypeNames->Float, + usdTime); + // Roughness _AuthorShaderInputFromShadingNodeAttr( depNodeFn, @@ -306,6 +314,7 @@ PxrMayaUsdPreviewSurface_Writer::GetShadingAttributeNameForMayaAttrName(const Tf || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->NormalAttrName || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->OcclusionAttrName || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->OpacityAttrName + || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->OpacityThresholdAttrName || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->RoughnessAttrName || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->SpecularColorAttrName || mayaAttrName == PxrMayaUsdPreviewSurfaceTokens->UseSpecularWorkflowAttrName) { diff --git a/test/lib/usd/translators/CMakeLists.txt b/test/lib/usd/translators/CMakeLists.txt index 08e8064550..4073366f75 100644 --- a/test/lib/usd/translators/CMakeLists.txt +++ b/test/lib/usd/translators/CMakeLists.txt @@ -24,6 +24,7 @@ set(TEST_SCRIPT_FILES # PPT, 17-Jun-20. testUsdExportParticles.py testUsdExportPref.py + testUsdExportPreviewShader.py # Following test runs only in legacy render layer mode, otherwise skipped. # Legacy render layers are deprecated, and should not be used. # To avoid skipping and run in legacy render layer mode, diff --git a/test/lib/usd/translators/testUsdExportPreviewShader.py b/test/lib/usd/translators/testUsdExportPreviewShader.py new file mode 100644 index 0000000000..0324fbebb9 --- /dev/null +++ b/test/lib/usd/translators/testUsdExportPreviewShader.py @@ -0,0 +1,69 @@ +#!/pxrpythonsubst + +# +# Copyright 2020 Apple +# +# 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. +# + +import os +import unittest + +import fixturesUtils +from maya import cmds +from maya import standalone +from pxr import Usd + + +def apply_preview_surface(node, shader=None): + """Apply a USD Preview Surface shader to the given node""" + shader = shader or cmds.shadingNode('usdPreviewSurface', asShader=True) + cmds.select(node) + cmds.hyperShade(assign=shader) + return shader + + +class testUsdExportPreviewShader(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.temp_dir = fixturesUtils.setUpClass(__file__) + + @classmethod + def tearDownClass(cls): + standalone.uninitialize() + + def testExportOpacityThreshold(self): + """Make sure that opacity threshold gets written out correctly""" + target = 0.5 + cmds.file(new=True, force=True) + + transform, shape = cmds.polyCube() + shader = apply_preview_surface(transform) + + cmds.setAttr("{}.opacityThreshold".format(shader), target) + + temp_file = os.path.join(self.temp_dir, "opacity_threshold.usda") + cmds.select(transform) + cmds.mayaUSDExport(f=temp_file) + + stage = Usd.Stage.Open(temp_file) + prim = stage.GetPrimAtPath("/pCube1/Looks/usdPreviewSurface1SG/usdPreviewSurface1") + attr = prim.GetAttribute("inputs:opacityThreshold") + val = attr.Get() + + self.assertEqual(val, target) + + +if __name__ == '__main__': + unittest.main(verbosity=2)