Skip to content

Commit

Permalink
Merge pull request #4031 from Autodesk/gamaj/MAYA-133671/allow_topo_h…
Browse files Browse the repository at this point in the history
…andler_to_handle_untextured

MAYA-133671 - Add textured mode handling to topo grapher
  • Loading branch information
seando-adsk authored Dec 6, 2024
2 parents 1193416 + fe07c89 commit 4e01a71
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 8 deletions.
36 changes: 32 additions & 4 deletions lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "ShaderGenUtil.h"

#include "LobePruner.h"
#include "MaterialXCore/Types.h"

#include <mayaUsd/render/MaterialXGenOgsXml/CombinedMaterialXVersion.h>

Expand Down Expand Up @@ -56,17 +57,26 @@ const std::string& TopoNeutralGraph::getMaterialName()
return kMaterialName;
}

TopoNeutralGraph::TopoNeutralGraph(const mx::ElementPtr& material) { computeGraph(material); }
TopoNeutralGraph::TopoNeutralGraph(const mx::ElementPtr& material) { computeGraph(material, true); }

TopoNeutralGraph::TopoNeutralGraph(
const mx::ElementPtr& material,
const LobePruner::Ptr& lobePruner)
{
_lobePruner = lobePruner;
computeGraph(material);
computeGraph(material, true);
}

void TopoNeutralGraph::computeGraph(const mx::ElementPtr& material)
TopoNeutralGraph::TopoNeutralGraph(
const mx::ElementPtr& material,
const LobePruner::Ptr& lobePruner,
bool textured)
{
_lobePruner = lobePruner;
computeGraph(material, textured);
}

void TopoNeutralGraph::computeGraph(const mx::ElementPtr& material, bool textured)
{
if (!material) {
throw mx::Exception("Invalid material element");
Expand Down Expand Up @@ -138,7 +148,25 @@ void TopoNeutralGraph::computeGraph(const mx::ElementPtr& material)
if (!sourceInput) {
continue;
}
auto connectedNode = sourceInput->getConnectedNode();
auto connectedNode = sourceInput->getConnectedNode();

// In textured mode we traverse everything, but in untextured mode we only traverse PBR
// level connections.
static const auto kPbrConnectionTypes = std::set<std::string>
{
#if MX_COMBINED_VERSION >= 13807
mx::BSDF_TYPE_STRING, mx::EDF_TYPE_STRING, mx::VDF_TYPE_STRING,
#else
"BSDF", "EDF", "VDF",
#endif
mx::SURFACE_SHADER_TYPE_STRING, mx::DISPLACEMENT_SHADER_TYPE_STRING,
mx::VOLUME_SHADER_TYPE_STRING
};

if (!textured && kPbrConnectionTypes.count(sourceInput->getType()) == 0) {
connectedNode = nullptr;
}

const std::string defaultGeomPropString = gatherDefaultGeomProp(*sourceInput);
if (connectedNode) {
auto destConnectedIt = _nodeMap.find(connectedNode->getNamePath());
Expand Down
30 changes: 28 additions & 2 deletions lib/mayaUsd/render/MaterialXGenOgsXml/ShaderGenUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,34 @@ namespace ShaderGenUtil {
class MAYAUSD_CORE_PUBLIC TopoNeutralGraph
{
public:
/*! Creates a barebones TopoNeutralGraph that will process the provided material and generate a
* topo neutral version of it.
* @param[in] material the material to process
*/
explicit TopoNeutralGraph(const mx::ElementPtr& material);
explicit TopoNeutralGraph(const mx::ElementPtr& material, const LobePruner::Ptr& library);

/*! Creates a TopoNeutralGraph that will process the provided material and generate a topo
* neutral version of it. It will also substitute lobe pruned categories if a LobePruner is
* provided.
* @param[in] material the material to process
* @param[in] lobePruner an instance of a LobePruner. These are usually singletons that
* accumulate pruned NodeDefs
*/
TopoNeutralGraph(const mx::ElementPtr& material, const LobePruner::Ptr& lobePruner);

/*! Creates a TopoNeutralGraph that will process the provided material and generate a topo
* neutral version of it. It will also substitute lobe pruned categories if a LobePruner is
* provided.
* @param[in] material the material to process
* @param[in] lobePruner an instance of a LobePruner. These are usually singletons that
* accumulate pruned NodeDefs
* @param[in] textured is true if the full material is to be processed. When false, we will
* generate an untextured topo neutral material instead
*/
TopoNeutralGraph(
const mx::ElementPtr& material,
const LobePruner::Ptr& lobePruner,
bool textured);
~TopoNeutralGraph() = default;

TopoNeutralGraph() = delete;
Expand Down Expand Up @@ -57,7 +83,7 @@ class MAYAUSD_CORE_PUBLIC TopoNeutralGraph
mx::NodeGraphPtr& getNodeGraph();

protected:
void computeGraph(const mx::ElementPtr& material);
void computeGraph(const mx::ElementPtr& material, bool textured);
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);
Expand Down
16 changes: 16 additions & 0 deletions lib/mayaUsdAPI/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ struct TopoNeutralGraphImpl
{
}

TopoNeutralGraphImpl(
const MaterialX::ElementPtr& material,
const LobePruner::Ptr& lobePruner,
bool textured)
: _topoGraph(material, lobePruner->_imp->_lobePruner, textured)
{
}

MaterialXMaya::ShaderGenUtil::TopoNeutralGraph _topoGraph;
};

Expand All @@ -184,6 +192,14 @@ TopoNeutralGraph::TopoNeutralGraph(
{
}

TopoNeutralGraph::TopoNeutralGraph(
const MaterialX::ElementPtr& material,
const LobePruner::Ptr& lobePruner,
bool textured)
: _imp(new TopoNeutralGraphImpl(material, lobePruner, textured))
{
}

// When using a pimpl you need to define the destructor here in the
// .cpp so the compiler has access to the impl.
TopoNeutralGraph::~TopoNeutralGraph() = default;
Expand Down
30 changes: 28 additions & 2 deletions lib/mayaUsdAPI/render.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,34 @@ class MAYAUSD_API_PUBLIC LobePruner
class MAYAUSD_API_PUBLIC TopoNeutralGraph
{
public:
TopoNeutralGraph(const MaterialX::ElementPtr&);
TopoNeutralGraph(const MaterialX::ElementPtr&, const LobePruner::Ptr& lobePruner);
/*! Creates a barebones TopoNeutralGraph that will process the provided material and generate a
* topo neutral version of it.
* @param[in] material the material to process
*/
TopoNeutralGraph(const MaterialX::ElementPtr& material);

/*! Creates a TopoNeutralGraph that will process the provided material and generate a topo
* neutral version of it. It will also substitute lobe pruned categories if a LobePruner is
* provided.
* @param[in] material the material to process
* @param[in] lobePruner an instance of a LobePruner. These are usually singletons that
* accumulate pruned NodeDefs
*/
TopoNeutralGraph(const MaterialX::ElementPtr& material, const LobePruner::Ptr& lobePruner);

/*! Creates a TopoNeutralGraph that will process the provided material and generate a topo
* neutral version of it. It will also substitute lobe pruned categories if a LobePruner is
* provided.
* @param[in] material the material to process
* @param[in] lobePruner an instance of a LobePruner. These are usually singletons that
* accumulate pruned NodeDefs
* @param[in] textured is true if the full material is to be processed. When false, we will
* generate an untextured topo neutral material instead
*/
TopoNeutralGraph(
const MaterialX::ElementPtr& material,
const LobePruner::Ptr& lobePruner,
bool textured);
~TopoNeutralGraph();

MaterialX::NodeGraphPtr nodeGraph();
Expand Down
48 changes: 48 additions & 0 deletions test/lib/mayaUsd/utils/test_ShaderGenUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,51 @@ TEST(ShaderGenUtils, lobePruner)
optimizedNodeId = lobePruner->getOptimizedNodeId(usdNode);
ASSERT_TRUE(optimizedNodeId.IsEmpty());
}

TEST(ShaderGenUtils, lobePrunedTopoGraph)
{
namespace sgu = MaterialXMaya::ShaderGenUtil;

auto testPath = mx::FilePath(MATERIALX_TEST_DATA);

auto library = mx::createDocument();
ASSERT_TRUE(library != nullptr);
auto searchPath = PXR_NS::HdMtlxSearchPaths();
mx::loadLibraries({}, searchPath, library);

auto doc = mx::createDocument();
doc->importLibrary(library);

auto lobePruner = sgu::LobePruner::create();
lobePruner->setLibrary(doc);

const mx::XmlReadOptions readOptions;
mx::readFromXmlFile(doc, testPath / "MultiConnect1_topo.mtlx", mx::EMPTY_STRING, &readOptions);

const auto originalCategory = doc->getNode("N1")->getCategory();

auto topoNetwork
= MaterialXMaya::ShaderGenUtil::TopoNeutralGraph(doc->getNode("N0"), lobePruner, false);

// In thory, we should have an empty NodeGraph since we are in untextured mode:
ASSERT_TRUE(topoNetwork.getNodeGraph()->getNodes().empty());

// Should have only 2 nodes:
ASSERT_EQ(topoNetwork.getDocument()->getNodes().size(), 2);

// Surface should be optimized and fully unconnected:
const auto surface = topoNetwork.getDocument()->getNode("N1");

const auto surfaceCategory = surface->getCategory();

// Should begin with standard_surface
ASSERT_TRUE(surfaceCategory.rfind(originalCategory, 0) == 0);

// But have a LobePruner optimization:
ASSERT_TRUE(surfaceCategory.size() > originalCategory.size());

// Which should be in the library of the LobePruner:
topoNetwork.getDocument()->importLibrary(doc);
const auto optNodeDef = surface->getNodeDef();
ASSERT_TRUE(optNodeDef != nullptr);
}

0 comments on commit 4e01a71

Please sign in to comment.