Skip to content

Commit

Permalink
added an example procedural and catched to cases of invalid input
Browse files Browse the repository at this point in the history
  • Loading branch information
krohmerNV committed Nov 28, 2024
1 parent e0d7e39 commit 3d3ed4c
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
Input and output variables can just be used as if they where declared and initialized with the corresponding defaults before.
Functions are not allowed to return, also no early returns allowed.
All input and output names in the MDL implementation have a "mxp_" prefix in order to avoid collisions with reserved names.
When adding comments in the inline sourcecode, use `/* comment */` as `//` is not supported at this point.
-->
<implementation
name="IM_custom_inline_node"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

<!-- implementation -->
<!-- specifies where to find the implementation of the custom node.
There is no need to add a signature because it will be generated from the definition.
All input and output names in the MDL implementation have a "mxp_" prefix in order to avoid collisions with reserved names.
Input and output names in the MDL implementation have a "mxp_" prefix in case they would collide with reserved names.
Note, the defaults for output parameters (if present) must be matched in the MDL implementation
in case the outputs remain unchanged in at least one code path.
-->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0"?>
<materialx version="1.39">

<!-- definition -->
<!-- specifies the interface of the node, including:
- the `node` that defines the name of the element during instantiation
- all input parameter types and names
- all output parameter types and names
- all inputs and outputs can have defaults
- the `name` that needs to br referenced when adding the implementation with the actual source code
-->
<nodedef name="ND_example_procedural" node="example_procedural" nodegroup="custom" doc="A simple example that creates a color.">
<input name="texcoord" type="vector2" />
<input name="thickness" type="float" value="1.0" />
<input name="power" type="float" value="1.0" />
<input name="time" type="float" value="0.0" />
<input name="iterations" type="integer" value="5" />
<input name="offset" type="float" value="1.85" />
<output name="out" type="color3" />
</nodedef>

<!-- implementation -->
<!-- specifies the body of the function.
There is no need to add a signature because it will be generated from the definition.
Input and output variables can just be used as if they where declared and initialized with the corresponding defaults before.
Functions are not allowed to return, also no early returns allowed.
All input and output names in the MDL implementation have a "mxp_" prefix in order to avoid collisions with reserved names.
When adding comments in the inline sourcecode, use `/* comment */` as `//` is not supported at this point.
-->
<implementation
name="IM_example_procedural"
nodedef="ND_example_procedural"
target="genmdl"
sourcecode="
/* uv with origin in the center */
float2 uv = math::frac(mxp_texcoord) * 2.0 - 1.0;
/* accumulate rings of different size */
mxp_out = color(0.0);
for (int i = 0; i < mxp_iterations; ++i)
{
/* signed distance function for the color selection */
float d = math::length(uv);
/* cosine based coloring */
float phi = d + i * 0.33;
color tint_contrib = math::cos(math::TWO_PI * (float3(0.0, 0.1, 0.2) + phi)) * 0.5 + 0.5;
/* signed distance function for a ring + add some contrast */
d = math::abs(math::sin(d * 16 + mxp_time) * 0.0625);
d = math::pow(0.005 * mxp_thickness / math::max(d, 0.0001), mxp_power);
/* add contribution */
mxp_out += tint_contrib * d;
/* offset the coordinate for the next iteration */
uv = math::frac(uv * mxp_offset) - 0.5;
}
" />

<!-- instantiations -->
<!-- uses the node above in material graph -->
<texcoord name="texcoord1" type="vector2" />

<example_procedural name="example_procedural1" type="color3">
<input name="texcoord" type="vector2" nodename="texcoord1" />
<input name="power" type="float" value="1.25" />
</example_procedural>

<multiply name="emission_intensity" type="color3">
<input name="in1" type="color3" nodename="example_procedural1" />
<input name="in2" type="color3" value="0.3183 0.3183 0.3183" />
</multiply>
<uniform_edf name="emission" type="EDF">
<input name="color" type="color3" nodename="emission_intensity" />
</uniform_edf>
<surface name="surface1" type="surfaceshader">
<input name="edf" type="EDF" nodename="emission" />
</surface>
<surfacematerial name="example_procedural_test" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="surface1" />
</surfacematerial>

</materialx>
4 changes: 4 additions & 0 deletions source/MaterialXGenMdl/MdlShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ ShaderNodeImplPtr MdlShaderGenerator::getImplementation(const NodeDef& nodedef,
{
impl = CustomCodeNodeMdl::create();
}
else if (file.empty() && sourcecode.empty())
{
throw ExceptionShaderGenError("No valid MDL implementation found for '" + name + "'");
}
else
{
// Fall back to source code implementation.
Expand Down
4 changes: 4 additions & 0 deletions source/MaterialXGenMdl/Nodes/CustomNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ void CustomCodeNodeMdl::initializeForInlineSourceCode(const InterfaceElement& el
{
throw ExceptionShaderGenError("No source code was specified for the implementation '" + impl.getName() + "'");
}
if (_inlineSourceCode.find("//") != string::npos)
{
throw ExceptionShaderGenError("Source code contains unsupported comments '//', please use '/* comment */' instead in '" + impl.getName() + "'");
}

NodeDefPtr nodeDef = impl.getNodeDef();
_inlineFunctionName = nodeDef->getName();
Expand Down
13 changes: 3 additions & 10 deletions source/MaterialXGenShader/Nodes/SourceCodeNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,16 @@ void SourceCodeNode::initialize(const InterfaceElement& element, GenContext& con
const Implementation& impl = static_cast<const Implementation&>(element);

// Get source code from either an attribute or a file.
if (_functionSource.empty())
{
// only read the attribute if empty to allow inherited classes to override
_functionSource = impl.getAttribute("sourcecode");
}
_functionSource = impl.getAttribute("sourcecode");
if (_functionSource.empty())
{
resolveSourceCode(element, context);
}

// Find the function name to use
// If no function is given the source will be inlined.
if (_functionName.empty())
{
// only read the attribute if empty to allow inherited classes to override
_functionName = impl.getAttribute("function");
}
_functionName = impl.getAttribute("function");

_inlined = _functionName.empty();
if (!_inlined)
{
Expand Down
2 changes: 1 addition & 1 deletion source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void MdlShaderGeneratorTester::compileSource(const std::vector<mx::FilePath>& so

CHECK(returnValue == 0);
}
if (false) //!renderExec.empty()) // render if renderer is availabe
if (!renderExec.empty()) // render if renderer is available
{
std::string renderCommand = renderExec;

Expand Down
4 changes: 0 additions & 4 deletions source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,10 +704,6 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
size_t documentIndex = 0;
for (const auto& doc : _documents)
{
std::string uri = doc->getSourceUri();
// if (uri.find("custom_inline_node_reserved_words") == std::string::npos)
// continue;

// Apply optional preprocessing.
preprocessDocument(doc);
_shaderGenerator->registerShaderMetadata(doc, context);
Expand Down

0 comments on commit 3d3ed4c

Please sign in to comment.