Skip to content

Commit

Permalink
Initial nprlib with viewdirection node (AcademySoftwareFoundation#1631)
Browse files Browse the repository at this point in the history
This changelist introduces an NPR (non-photorealistic rendering) data library to MaterialX, initially consisting of a single `viewdirection` node.

The NPR data library is designed for the portable expression of artistic, non-physically-based materials, with common examples being cartoon shading, architectural diagrams, and edge highlighting.  In future versions of MaterialX, we expect this data library to be extended with additional primitives and artist-facing graphs as they are requested by the graphics community and approved by the MaterialX TSC.

For shader generation, MaterialX initially supports the NPR data library in GLSL, ESSL, MSL, and OSL, with MDL being omitted for now, based on intentional restrictions in its design philosophy.
  • Loading branch information
jstone-lucasfilm authored Jan 4, 2024
1 parent 473d563 commit 39d6d5b
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 69 deletions.
17 changes: 17 additions & 0 deletions libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<materialx version="1.38">
<!--
Copyright Contributors to the MaterialX Project
SPDX-License-Identifier: Apache-2.0
Declarations for GLSL implementations of standard nodes included in the MaterialX specification.
-->

<!-- ======================================================================== -->
<!-- View-dependent nodes -->
<!-- ======================================================================== -->

<!-- <viewdirection> -->
<implementation name="IM_viewdirection_vector3_genglsl" nodedef="ND_viewdirection_vector3" target="genglsl"/>

</materialx>
17 changes: 17 additions & 0 deletions libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<materialx version="1.38">
<!--
Copyright Contributors to the MaterialX Project
SPDX-License-Identifier: Apache-2.0
Declarations for MDL implementations of standard nodes included in the MaterialX specification.
-->

<!-- ======================================================================== -->
<!-- View-dependent nodes -->
<!-- ======================================================================== -->

<!-- <viewdirection> -->
<implementation name="IM_viewdirection_vector3_genmdl" nodedef="ND_viewdirection_vector3" sourcecode="mx::stdlib::mx_viewdirection_vector3()" target="genmdl"/>

</materialx>
17 changes: 17 additions & 0 deletions libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<materialx version="1.38">
<!--
Copyright Contributors to the MaterialX Project
SPDX-License-Identifier: Apache-2.0
Declarations for MSL implementations of standard nodes included in the MaterialX specification.
-->

<!-- ======================================================================== -->
<!-- View-dependent nodes -->
<!-- ======================================================================== -->

<!-- <viewdirection> -->
<implementation name="IM_viewdirection_vector3_genmsl" nodedef="ND_viewdirection_vector3" target="genmsl"/>

</materialx>
17 changes: 17 additions & 0 deletions libraries/nprlib/genosl/nprlib_genosl_impl.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<materialx version="1.38">
<!--
Copyright Contributors to the MaterialX Project
SPDX-License-Identifier: Apache-2.0
Declarations for OSL implementations of standard nodes included in the MaterialX specification.
-->

<!-- ======================================================================== -->
<!-- View-dependent nodes -->
<!-- ======================================================================== -->

<!-- <viewdirection> -->
<implementation name="IM_viewdirection_vector3_genosl" nodedef="ND_viewdirection_vector3" sourcecode="transform({{space}}, I)" target="genosl" />

</materialx>
23 changes: 23 additions & 0 deletions libraries/nprlib/nprlib_defs.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<materialx version="1.38">
<!--
Copyright Contributors to the MaterialX Project
SPDX-License-Identifier: Apache-2.0
Declarations of standard data types and nodes included in the MaterialX specification.
-->

<!-- ======================================================================== -->
<!-- View-dependent nodes -->
<!-- ======================================================================== -->

<!--
Node: <viewdirection>
The current scene view direction, as defined by the shading environment.
-->
<nodedef name="ND_viewdirection_vector3" node="viewdirection" nodegroup="npr">
<input name="space" type="string" value="world" enum="model,object,world" uniform="true" />
<output name="out" type="vector3" default="0.0, 0.0, 1.0" />
</nodedef>

</materialx>
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<?xml version="1.0"?>
<materialx version="1.38">
<materialx version="1.38" colorspace="lin_rec709">

<!-- Custom node: <viewdir> -->
<!-- Required by environment shader graph below -->
<nodedef name="ND_viewdir_vector3" node="viewdir">
<output name="out" type="vector3" default="0.0, 0.0, 1.0" />
</nodedef>
<implementation name="IM_viewdir_vector3_genglsl" nodedef="ND_viewdir_vector3" target="genglsl" />
<implementation name="IM_viewdir_vector3_genmsl" nodedef="ND_viewdir_vector3" target="genmsl" />
<nodegraph name="environmentDraw">
<nodegraph name="envMap">

<!-- Get view direction -->
<viewdir name="viewDir" type="vector3" />
<viewdirection name="viewDir" type="vector3" />

<!-- Compute longitude coordinate -->
<atan2 name="angleXZ" type="float">
Expand Down Expand Up @@ -46,11 +39,11 @@
<input name="in2" type="float" nodename="latitude" />
</combine2>
<image name="envImage" type="color3">
<input name="file" type="filename" value="resources/Lights/san_giuseppe_bridge.hdr" uniform="true" />
<input name="file" type="filename" value="resources/Lights/san_giuseppe_bridge.hdr" />
<input name="texcoord" type="vector2" nodename="mapUvs" />
<input name="uaddressmode" type="string" value="periodic" uniform="true" />
<input name="vaddressmode" type="string" value="clamp" uniform="true" />
<input name="filtertype" type="string" value="linear" uniform="true" />
<input name="uaddressmode" type="string" value="periodic" />
<input name="vaddressmode" type="string" value="clamp" />
<input name="filtertype" type="string" value="linear" />
</image>

<!-- Return the resulting color -->
Expand Down
2 changes: 1 addition & 1 deletion resources/Materials/TestSuite/_options.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
<input name="extraLibraryPaths" type="string" value="" />

<!-- List of document paths for render tests -->
<input name="renderTestPaths" type="string" value="resources/Materials/Examples/StandardSurface,resources/Materials/TestSuite/stdlib/color_management,resources/Materials/TestSuite/stdlib/convolution,resources/Materials/TestSuite/stdlib/geometric,resources/Materials/TestSuite/stdlib/noise,resources/Materials/TestSuite/pbrlib" />
<input name="renderTestPaths" type="string" value="resources/Materials/Examples/StandardSurface,resources/Materials/TestSuite/stdlib/color_management,resources/Materials/TestSuite/stdlib/convolution,resources/Materials/TestSuite/stdlib/geometric,resources/Materials/TestSuite/stdlib/noise,resources/Materials/TestSuite/pbrlib,resources/Materials/TestSuite/nprlib" />

<!-- Enable reference quality rendering. Default is false. -->
<input name="enableReferenceQuality" type="boolean" value="false" />
Expand Down
28 changes: 28 additions & 0 deletions resources/Materials/TestSuite/nprlib/edge_brighten.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
<nodegraph name="edge_brighten">
<viewdirection name="viewdirection_vector3" type="vector3" />
<normal name="normal_vector3" type="vector3" />
<multiply name="multiply_vector3" type="vector3">
<input name="in1" type="vector3" nodename="viewdirection_vector3" />
<input name="in2" type="float" value="-1" />
</multiply>
<dotproduct name="dotproduct_vector3" type="float">
<input name="in1" type="vector3" nodename="multiply_vector3" />
<input name="in2" type="vector3" nodename="normal_vector3" />
</dotproduct>
<clamp name="clamp_float" type="float">
<input name="in" type="float" nodename="dotproduct_vector3" />
</clamp>
<power name="power_float" type="float">
<input name="in1" type="float" nodename="clamp_float" />
<input name="in2" type="float" value="0.2" />
</power>
<mix name="mix_color3" type="color3">
<input name="fg" type="color3" value="0, 0.0986187, 0.186275" />
<input name="bg" type="color3" value="0.735294, 0.735294, 0.735294" />
<input name="mix" type="float" nodename="power_float" />
</mix>
<output name="out" type="color3" nodename="mix_color3" />
</nodegraph>
</materialx>
25 changes: 25 additions & 0 deletions resources/Materials/TestSuite/nprlib/starfield.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
<nodegraph name="starfield">
<viewdirection name="viewDir" type="vector3" />
<multiply name="multiply_vector3FA" type="vector3">
<input name="in1" type="vector3" nodename="viewDir" />
<input name="in2" type="float" value="260" />
</multiply>
<noise3d name="noise3d_float" type="float">
<input name="position" type="vector3" nodename="multiply_vector3FA" />
</noise3d>
<contrast name="contrast_float" type="float">
<input name="in" type="float" nodename="noise3d_float" />
<input name="amount" type="float" value="5" />
<input name="pivot" type="float" value="0.8" />
</contrast>
<clamp name="clamp_float" type="float">
<input name="in" type="float" nodename="contrast_float" />
</clamp>
<convert name="convert_float_color3" type="color3">
<input name="in" type="float" nodename="clamp_float" />
</convert>
<output name="out" type="color3" nodename="convert_float_color3" />
</nodegraph>
</materialx>
3 changes: 3 additions & 0 deletions source/MaterialXGenGlsl/GlslShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <MaterialXGenGlsl/Nodes/GeomPropValueNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/FrameNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/TimeNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/UnlitSurfaceNodeGlsl.h>
#include <MaterialXGenGlsl/Nodes/LightNodeGlsl.h>
Expand Down Expand Up @@ -196,6 +197,8 @@ GlslShaderGenerator::GlslShaderGenerator() :
registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, FrameNodeGlsl::create);
// <!-- <time> -->
registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, TimeNodeGlsl::create);
// <!-- <viewdirection> -->
registerImplementation("IM_viewdirection_vector3_" + GlslShaderGenerator::TARGET, ViewDirectionNodeGlsl::create);

// <!-- <surface> -->
registerImplementation("IM_surface_" + GlslShaderGenerator::TARGET, SurfaceNodeGlsl::create);
Expand Down
55 changes: 55 additions & 0 deletions source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//

#include <MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h>

#include <MaterialXGenShader/Shader.h>

MATERIALX_NAMESPACE_BEGIN

ShaderNodeImplPtr ViewDirectionNodeGlsl::create()
{
return std::make_shared<ViewDirectionNodeGlsl>();
}

void ViewDirectionNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const
{
ShaderStage& vs = shader.getStage(Stage::VERTEX);
ShaderStage& ps = shader.getStage(Stage::PIXEL);

addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs);
addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps);
addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps);
}

void ViewDirectionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
{
const ShaderGenerator& shadergen = context.getShaderGenerator();

DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
{
VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* position = vertexData[HW::T_POSITION_WORLD];
if (!position->isEmitted())
{
position->setEmitted();
shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage);
}
}

DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
{
VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* position = vertexData[HW::T_POSITION_WORLD];
shadergen.emitLineBegin(stage);
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage);
shadergen.emitLineEnd(stage);
}
}

MATERIALX_NAMESPACE_END
26 changes: 26 additions & 0 deletions source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//

#ifndef MATERIALX_VIEWDIRECTIONNODEGLSL_H
#define MATERIALX_VIEWDIRECTIONNODEGLSL_H

#include <MaterialXGenGlsl/GlslShaderGenerator.h>

MATERIALX_NAMESPACE_BEGIN

/// ViewDirection node implementation for GLSL
class MX_GENGLSL_API ViewDirectionNodeGlsl : public GlslImplementation
{
public:
static ShaderNodeImplPtr create();

void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;

void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
};

MATERIALX_NAMESPACE_END

#endif
16 changes: 16 additions & 0 deletions source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,22 @@ export float mx_time_float(
return ::state::animation_time();
}

export float3 mx_viewdirection_vector3(
uniform mx_coordinatespace_type mxp_space = mx_coordinatespace_type(mx_coordinatespace_type_world)
[[
anno::description("Enumeration {model,object,world}."),
anno::unused()
]]
)
[[
anno::description("Node Group: nprlib")
]]
{
// Not implemented: mx_viewdirection_vector3
float3 defaultValue = float3(0.0, 0.0, 1.0);
return defaultValue;
}

export color mx_modulo_color3(
color mxp_in1 = color(0.0, 0.0, 0.0),
color mxp_in2 = color(1.0, 1.0, 1.0)
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXGenMsl/MslShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <MaterialXGenMsl/Nodes/GeomPropValueNodeMsl.h>
#include <MaterialXGenMsl/Nodes/FrameNodeMsl.h>
#include <MaterialXGenMsl/Nodes/TimeNodeMsl.h>
#include <MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h>
#include <MaterialXGenMsl/Nodes/SurfaceNodeMsl.h>
#include <MaterialXGenMsl/Nodes/UnlitSurfaceNodeMsl.h>
#include <MaterialXGenMsl/Nodes/LightNodeMsl.h>
Expand Down Expand Up @@ -200,6 +201,8 @@ MslShaderGenerator::MslShaderGenerator() :
registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, FrameNodeMsl::create);
// <!-- <time> -->
registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, TimeNodeMsl::create);
// <!-- <viewdirection> -->
registerImplementation("IM_viewdirection_vector3_" + MslShaderGenerator::TARGET, ViewDirectionNodeMsl::create);

// <!-- <surface> -->
registerImplementation("IM_surface_" + MslShaderGenerator::TARGET, SurfaceNodeMsl::create);
Expand Down
55 changes: 55 additions & 0 deletions source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//

#include <MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h>

#include <MaterialXGenShader/Shader.h>

MATERIALX_NAMESPACE_BEGIN

ShaderNodeImplPtr ViewDirectionNodeMsl::create()
{
return std::make_shared<ViewDirectionNodeMsl>();
}

void ViewDirectionNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const
{
ShaderStage& vs = shader.getStage(Stage::VERTEX);
ShaderStage& ps = shader.getStage(Stage::PIXEL);

addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs);
addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps);
addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps);
}

void ViewDirectionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
{
const ShaderGenerator& shadergen = context.getShaderGenerator();

DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
{
VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* position = vertexData[HW::T_POSITION_WORLD];
if (!position->isEmitted())
{
position->setEmitted();
shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage);
}
}

DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
{
VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* position = vertexData[HW::T_POSITION_WORLD];
shadergen.emitLineBegin(stage);
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage);
shadergen.emitLineEnd(stage);
}
}

MATERIALX_NAMESPACE_END
Loading

0 comments on commit 39d6d5b

Please sign in to comment.