Node Definitions

MaterialX ships with definitions which are partitioned into a few semantic categories:

  • stdlib: A set of core or "standard" definitions. This includes definitions for vector, color and image manipulation
  • pbrlib: A set of definitions representing physically based shader nodes.
  • bxdf: A set of industry standard shading models.
  • translation: A set of shading model translators

Each set can be thought of as a library. There is not specific "library" format, but instead each file is a MaterialX document.

Shown below are the definition dependencies. Definitions in higher libraries depend on definitions in "lower" libraries. Custom definitions can be built using existing standard definitions or other custom definitions. For example the 'pbr' library definitions use 'stdlib' definitions.

In MaterialX a node definition is called a <nodedef>.

  • A definition should have 1 or more input and output parameters for data flow to occur.
  • The nodedef itself as well as it's parameters have attributes.
  • The identifier for all attributes are lowercase strings.
Required Attributes

Required definition attributes include:
  • A unique name attribute

    For the libraries shipping with MaterialX a "ND_" prefix is used as a prefix with the the follow proposed syntax template to provide long term uniqueness:

    ND_<node category>_<type>[_<version>]

    While it is possible to change this name later on, this can cause issues with dependents that reference this name directly. This includes references for node instances which are stored in a MaterialX document.

  • A node attribute: This is the unique identifier to indicate the category of a node instance. One or more node definitions may use the same category, though each must have a unique "signature" (unique set of input, output, and token parameters).
  • An output type attributes: Different definitions for the same category can have the same or differing output types. If there is more than one output parameter on a definition then the definition's type is multioutput. In this case the individual output parameter types must be examined. Two or more definitions with the same category may have a "multioutput" type.

    Shown below are the preview images for an example definition with multiple outputs:

Additionally, it is worthwhile to consider versioning as being "required":
  • Though not strictly required it is very useful to have some description of the definition. This is specified in the doc attribute of the definition wherein all text is assumed to be in UTF-8 format.
  • It is recommended to have a version identifier and have this as part of the nodedef identifier. This avoids complications trying to add versioning later on. A recommended version number is either "1.0" , or a number matching the version of a given external specification. For example versions for "USD" definitions start with "2.x".

    An accompanying isdefaultversion attribute should be provided to determine the default definition to instantiate when no explicit version is specified. Versioning is also important to allow for "upgrade" logic support (future-proofing).

Node Groups

The node group (nodegroup) attribute is also recommended as being mandatory. It specifies the semantic used for evaluation including shader code generation. This includes:

  • "texture": Texture lookups test for this group identifier for example to perform convolutions
  • "adjustment": Used for heuristics to test for transparency
  • "conditional": Will cause branching in shader and re-generation is required for different conditions
  • "organization": Does not perform any computation
  • "translation:": Is a shading model translator

Inheritance

The inherit attribute indicates that a definition inherits it's interface from another definition. Inheritance allows for reuse and specialization and may also be used handling version changes. "inherit" should be set to another definition's unique "name".

For example the standard surface and USD texture definitions use inheritance. In one case to change the default values for inputs and in the latter to remove an output from a newer version.

For reference the set of input and output parameter attributes is shown below. This includes all the possible attribute and value variants. The set of attributes for inputs differ from those of outputs.

The required attributes are:

  • name: The name must be unique between all parameters on the definition.
  • type: The parameter type. Refer to the library glossary for a list of supported types.
Optional attributes include:
  • doc: Description (documentation) of the parameter. It is recommended to add a description so users will understand the meaning of the parameter.
  • uniform (input only): If specified the input data is uniform (vs varying) Only inputs can have this specified.
  • enumvalues and enum: The set of possible values and their corresponding labels respectively.
  • value (input only): The default value for inputs. Depending on the type, values may be qualified by additional attributes:
    • unit and unittype: For floats and vectors. Defines the unit and unit type for the input (e.g. "cm" and "distance"). Either one or the other may be specified. Refer to the library glossary for supported unit and unit types.
    • colorspace: For color3 and color4 and filename types. Defines the input color space. Note that a value of "none" means that this is a non-physical color and should not undergo any colorspace transforms. Refer to the library glossary for supported color space identifiers.
    • defaultgeomprop: String identifier of a default geometry stream to route as input. Refer to the library glossary for supported default geometry identifiers.
  • default (output only): The default value of an output when a node instance is disabled (The disable attribute is set true)
  • defaultinput (output only): The value on a definition's input to use by default value when a node instance is disabled.
Optional UI Attributes for Inputs
  • uimin, uisoftmin Hard and soft UI minimum value
  • uimax, uisoftmax Hard and soft UI maximum value
  • uistep UI step size value
  • uifolder Can be used to group parameters in the UI
  • uiadvanced Considered to be for "advanced" users

Implementations and Functional Graphs

A definition can be implemented either in code or using a functional node graph. A definition can have a different implementation depending on shading language target (e.g. OSL). Targets are provided as part of the standard definition libraries. The syntax is: gen_<language name>

A implementation represented as a node graph is inherently independent of a target (even though any node in graph may be target specific). The association between a node definition and a node graph can either be specified via the nodedef attribute on a node graph or via an <implementation> association as of version 1.38.4.

The recommended functional graph name should start with "NG_" and be of the form:

NG_<node category>_<type>[_<version>]

The following diagram shows the two possible ways implementations can be associated with definitions. As of 1.38.4 the <implementation> approach is recommended as it the same way that code associations are specified.

or

Functional Node Graph Diagrams

For the node definition documentation, diagrams of node graphs are generated from MaterialX library documents. The conventions for different components are shown in the sample diagram below:

  1. Nodes and node graphs are rectangular boxes (*)
  2. Outputs and inputs on functional node graphs are rounded and color-coded
  3. Conditional nodes are diamond shapes
  4. Data flow is drawn as lines with arrows (edges)
  5. An edge which connects to a node input is denoted using the syntax.input_name
(*) Note that even through the specification indicates that nodegraphs can contain other nodegraphs the current implementation (up to version 1.39) at time of writing does not support this. Thus the nodegraph box is not drawn for functional node graphs.

To retrieve information following are important API classes:

  • Document: document api to get nodedefs va getNodeDefs()
  • NodeDef: node definition
  • Implementation: nodedef definition implementation
  • NodeGraph: node graph implementation
  • Input: interface and node inputs for definitions and node graph implementation nodes
  • Output: outputs for definitions, node graphs and nodes

Input and output ports can be inherited from a parent definition. Note that in MaterialX terminology, getting active information means to get inherited information. Corresponding APIs having an "Active" API variants (e.g. getActiveValueElements() vs getValueElements()).

To get input and output attribute information the follow method is available: Element::getAttribute(<attribute name>)

The general method to get value information (marked as 'value' in the template) is: ValueElement::getValue()

The API calls have the same name for all supported APIs (Python, Javascript, C++)