Skip to content

Commit 3cf6abb

Browse files
Add HW generation support for compound material nodes (#2829)
This changelist adds hardware shader generation support for compound material nodes such as LamaSurface, which are defined as node graphs with material-type outputs. The following specific changes are included: - Add an `HwMaterialCompoundNode` class that extends `HwSurfaceNode` for nodegraphs with material-type outputs, discovering BSDF, EDF, and opacity input name mappings by analyzing the nodegraph's internal surface node connections. - Refactor `HwSurfaceNode` to resolve input names through virtual methods rather than hardcoded strings, and add null-safety for inputs that may not be present on compound material nodes. - Fix the fallback condition in `getShaderNodes` to check whether shader nodes were found, rather than whether the material node has inputs. - Fix `isTransparentSurface` to identify material nodes by output type rather than node category, so that compound material nodes are handled correctly. Fixes #1902 and #2811.
1 parent 24a9ddb commit 3cf6abb

7 files changed

Lines changed: 290 additions & 101 deletions

File tree

source/MaterialXCore/Material.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ vector<NodePtr> getShaderNodes(NodePtr materialNode, const string& nodeType, con
8888
}
8989
}
9090

91-
if (inputs.empty())
91+
if (shaderNodeVec.empty())
9292
{
9393
// Try to find material nodes in the implementation graph if any.
9494
// If a target is specified the nodedef for the given target is searched for.

source/MaterialXGenHw/HwShaderGenerator.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <MaterialXGenHw/HwConstants.h>
99
#include <MaterialXGenHw/HwLightShaders.h>
1010
#include <MaterialXGenHw/Nodes/HwLightCompoundNode.h>
11+
#include <MaterialXGenHw/Nodes/HwMaterialCompoundNode.h>
1112
#include <MaterialXGenShader/Exception.h>
1213
#include <MaterialXGenShader/Nodes/CompoundNode.h>
1314
#include <MaterialXGenShader/GenContext.h>
@@ -400,11 +401,17 @@ ShaderNodeImplPtr HwShaderGenerator::createShaderNodeImplForNodeGraph(const Node
400401

401402
const TypeDesc outputType = _typeSystem->getType(outputs[0]->getType());
402403

403-
// Use a compound implementation.
404+
// Use specialized implementations for nodes that output light shaders and materials.
404405
if (outputType == Type::LIGHTSHADER)
405406
{
406407
return HwLightCompoundNode::create();
407408
}
409+
if (outputType == Type::MATERIAL)
410+
{
411+
return HwMaterialCompoundNode::create();
412+
}
413+
414+
// Use the base implementation for nodes that output other types.
408415
return CompoundNode::create();
409416
}
410417

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// Copyright Contributors to the MaterialX Project
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
#include <MaterialXGenHw/Nodes/HwMaterialCompoundNode.h>
7+
8+
#include <MaterialXGenShader/ShaderNode.h>
9+
10+
#include <MaterialXCore/Definition.h>
11+
#include <MaterialXCore/Node.h>
12+
13+
MATERIALX_NAMESPACE_BEGIN
14+
15+
namespace
16+
{
17+
18+
const string MATERIAL_TYPE = "material";
19+
const string SURFACE_CATEGORY = "surface";
20+
21+
} // anonymous namespace
22+
23+
ShaderNodeImplPtr HwMaterialCompoundNode::create()
24+
{
25+
return std::make_shared<HwMaterialCompoundNode>();
26+
}
27+
28+
void HwMaterialCompoundNode::initialize(const InterfaceElement& element, GenContext& context)
29+
{
30+
ShaderNodeImpl::initialize(element, context);
31+
32+
if (!element.isA<NodeGraph>())
33+
{
34+
return;
35+
}
36+
37+
const NodeGraph& graph = static_cast<const NodeGraph&>(element);
38+
39+
// Find the material-type output and traverse upstream to discover the
40+
// surface node, reading its bsdf/edf/opacity interface name mappings.
41+
for (OutputPtr output : graph.getOutputs())
42+
{
43+
if (output->getType() == MATERIAL_TYPE)
44+
{
45+
for (Edge edge : output->traverseGraph())
46+
{
47+
ElementPtr upstream = edge.getUpstreamElement();
48+
NodePtr upstreamNode = upstream ? upstream->asA<Node>() : nullptr;
49+
if (upstreamNode && upstreamNode->getCategory() == SURFACE_CATEGORY)
50+
{
51+
InputPtr bsdfIn = upstreamNode->getInput("bsdf");
52+
if (bsdfIn && !bsdfIn->getInterfaceName().empty())
53+
{
54+
_bsdfInputName = bsdfIn->getInterfaceName();
55+
}
56+
57+
InputPtr edfIn = upstreamNode->getInput("edf");
58+
if (edfIn && !edfIn->getInterfaceName().empty())
59+
{
60+
_edfInputName = edfIn->getInterfaceName();
61+
}
62+
63+
InputPtr opacityIn = upstreamNode->getInput("opacity");
64+
if (opacityIn && !opacityIn->getInterfaceName().empty())
65+
{
66+
_opacityInputName = opacityIn->getInterfaceName();
67+
}
68+
69+
return;
70+
}
71+
}
72+
}
73+
}
74+
}
75+
76+
void HwMaterialCompoundNode::addClassification(ShaderNode& node) const
77+
{
78+
// Add SHADER|SURFACE so the top-level graph triggers the
79+
// surface shader code path in the HW pixel shader generators.
80+
node.addClassification(ShaderNode::Classification::SHADER |
81+
ShaderNode::Classification::SURFACE);
82+
}
83+
84+
const string& HwMaterialCompoundNode::getBsdfInputName() const
85+
{
86+
return _bsdfInputName;
87+
}
88+
89+
const string& HwMaterialCompoundNode::getEdfInputName() const
90+
{
91+
return _edfInputName;
92+
}
93+
94+
const string& HwMaterialCompoundNode::getOpacityInputName() const
95+
{
96+
return _opacityInputName;
97+
}
98+
99+
MATERIALX_NAMESPACE_END
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// Copyright Contributors to the MaterialX Project
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
#ifndef MATERIALX_HWMATERIALCOMPOUNDNODE_H
7+
#define MATERIALX_HWMATERIALCOMPOUNDNODE_H
8+
9+
#include <MaterialXGenHw/Nodes/HwSurfaceNode.h>
10+
11+
MATERIALX_NAMESPACE_BEGIN
12+
13+
/// MaterialCompound node implementation for hardware languages.
14+
/// Used for nodegraphs that output material type, such as LamaSurface.
15+
class MX_GENHW_API HwMaterialCompoundNode : public HwSurfaceNode
16+
{
17+
public:
18+
static ShaderNodeImplPtr create();
19+
20+
void initialize(const InterfaceElement& element, GenContext& context) override;
21+
void addClassification(ShaderNode& node) const override;
22+
23+
protected:
24+
const string& getBsdfInputName() const override;
25+
const string& getEdfInputName() const override;
26+
const string& getOpacityInputName() const override;
27+
28+
private:
29+
string _bsdfInputName;
30+
string _edfInputName;
31+
string _opacityInputName;
32+
};
33+
34+
MATERIALX_NAMESPACE_END
35+
36+
#endif

0 commit comments

Comments
 (0)