diff --git a/documents/Specification/inprog_v1.39/MaterialX.GeomExts.md b/documents/Specification/inprog_v1.39/MaterialX.GeomExts.md new file mode 100644 index 0000000000..fb0d581ed8 --- /dev/null +++ b/documents/Specification/inprog_v1.39/MaterialX.GeomExts.md @@ -0,0 +1,517 @@ + + + +# MaterialX Geometry Extensions + +**Version 1.39** +Doug Smythe - Industrial Light & Magic +Jonathan Stone - Lucasfilm Advanced Development Group +October 21, 2022 + + +# Introduction + +The core [**MaterialX Specification**](./MaterialX.Specification.md) defines a number of element types and specific functional node definitions which can be used to describe the structure of shading networks and materials, including the definitions and functionality of custom shading operations. + +There are many formats that can be used to describe the associations between shading materials and renderable geometry as well as various data and metadata associated with geometry. For performance and other reasons it is often desirable to use native application mechanisms or something like Pixar's USD[^1] to describe these associations. However, there is significant value in being able to store a complete description of a CG object "look" within a single application-independent file format. This document describes extensions to the core MaterialX Specification that can be used to define collections of geometries, geometric properties and their values per geometry, and assignment of materials, variants, visibility and rendering properties to specific geometries in named looks, either directly or via geometry name expressions or named collections. + + +## Table of Contents + +**[Introduction](#introduction)** + +**[Geometry Representation](#geometry-representation)** + [Lights](#lights) + [Geometry Name Expressions](#geometry-name-expressions) + [Collections](#collections) + [Geometry Prefixes](#geometry-prefixes) + +**[Additional MaterialX Data Types](#additional-materialx-data-types)** + +**[Additional Filename Substitutions](#additional-filename-substitutions)** + +**[Geometry Info Elements](#geometry-info-elements)** + [GeomInfo Definition](#geominfo-definition) + [GeomProp Elements](#geomprop-elements) + [Geometry Token Elements](#geometry-token-elements) + [TokenDefault Elements](#tokendefault-elements) + [Reserved GeomProp Names](#reserved-geomprop-names) + +**[Look and Property Elements](#look-and-property-elements)** + [Property Definition](#property-definition) + [Look Definition](#look-definition) + [Assignment Elements](#assignment-elements) + [MaterialAssign Elements](#materialassign-elements) + [VariantAssign Elements](#variantassign-elements) + [Visibility Elements](#visibility-elements) + [PropertyAssign Elements](#propertyassign-elements) + [Look Examples](#look-examples) + +**[References](#references)** + + + +# Geometry Representation + +Geometry is referenced by but not specifically defined within MaterialX content. The file in which geometry is defined can optionally be declared using `geomfile` attributes within any element; that `geomfile` declaration will then apply to any geometry name referenced within the scope of that element, e.g. any `geom` attributes, including those defining the contents of collections (but not when referencing the contents of a collection via a `collection` attribute). If a geomfile is not defined for the scope of any particular `geom` attribute, it is presumed that the host application can resolve the location of the geometry definition. + +The geometry naming conventions used in the MaterialX specification are designed to be compatible with those used in Alembic ([http://www.alembic.io/](http://www.alembic.io/)) and USD ([http://graphics.pixar.com/usd](http://graphics.pixar.com/usd)). "Geometry" can be any particular geometric object that a host application may support, including but not limited to polygons, meshes, subdivision surfaces, NURBS, implicit surfaces, particle sets, volumes, lights, procedurally-defined objects, etc. The only requirements for MaterialX are that geometries are named using the convention specified below, can be assigned to a material and can be rendered. + +The naming of geometry should follow a syntax similar to UNIX full paths: + +``` + /string1/string2/string3/... +``` + +E.g. an initial "/" followed by one or more hierarchy level strings separated by "/"s, ending with a final string and no "/". The strings making up the path component for a level of hierarchy cannot contain spaces or "/"s or any of the characters reserved for geometry name expressions (see below). Individual implementations may have further restrictions on what characters may be used for hierarchy level names, so for ultimate compatibility it is recommended to use names comprised only of upper- or lower-case letters, digits 0-9, and underscores ("_"). + +Geometry names (e.g. the full path name) must be unique within the entire set of geometries referenced in a setup. Note that _there is no implied transformation hierarchy in the specified geometry paths_: the paths are simply the names of the geometry. However, the path-like nature of geometry names can be used to benefit in geometry name expression pattern matching and assignments. + +Note: if a geometry mesh is divided into partitions, the syntax for the parent mesh would be: + +``` + /path/to/geom/meshname +``` + +and for the child partitions, the syntax would be: + +``` + /path/to/geom/meshname/partitionname +``` + +Assignments to non-leaf locations apply hierarchically to all geometries below the specified location, unless they are the target of another assignment. By extension, an assignment to "/" applies to _all _geometries within the MaterialX setup, unless they are the target of another assignment. + + +## Lights + +Computer Graphics assets often include lights as part of the asset, such as the headlights of a car. MaterialX does not define "light" objects per se, but instead allows referencing externally-defined light objects in the same manner as geometry, via a UNIX-like path. MaterialX does not describe the position, view or shape of a light object: MaterialX presumes that these properties are stored within the external representation. + +Light object geometries can be turned off (muted) in looks by making the light geometry invisible, assignment of "light"-context shader materials can be done using a <materialassign> within a <look>, and illumination and shadowing assignments can be handled using <visibility> declarations for the light geometry. See the [**Look Definition**](#look-definition) section below for details. + + + +## Geometry Name Expressions + +Certain elements in MaterialX files support geometry specification via expressions. The syntax for geometry name expressions in MaterialX largely follows that of “glob” patterns for filenames in Unix environments, with a few extensions for the specific needs of geometry references. + +Within a single hierarchy level (e.g. between "/"s): + +* `*` matches 0 or more characters +* `?` matches exactly one character +* `[]` are used to match any individual character within the brackets, with "-" meaning match anything between the character preceding and the character following the "-" +* `{}` are used to match any of the comma-separated strings or expressions within the braces + +Additionally, a `/` will match only exactly a single `/` in a geometry name, e.g. as a boundary for a hierarchy level, while a `//` will match a single `/`, or two `/`s any number of hierarchy levels apart; `//` can be used to specify a match at any hierarchy depth. If a geometry name ends with `//*`, the final `*` will only match leaf geometries in the hierarchy. A geometry name of `//*` by itself will match all leaf geometries in an entire scene, while the name `//*//` will match all geometries at any level, including nested geometries, and the name `/a/b/c//*//` will match all geometries at any level below `/a/b/c`. It should be noted that for a mesh with partitions, it is the partitions and not the mesh which are treated as leaf geometry by MaterialX geometry names using `//*`. + + + +## Collections + +Collections are recipes for building a list of geometries (which can be any path within the geometry hierarchy), which can be used as a shorthand for assignments to a (potentially large) number of geometries at once. Collections can be built up from lists of specific geometries, geometries matching defined geometry name expressions, other collections, or any combination of those. + +A **<collection>** element contains lists of geometry expressions and/or collections to be included, and an optional list of geometry expressions to be excluded: + +``` + +``` + +Either `includegeom` and/or `includecollection` must be specified. The `includegeom` and `includecollection` lists are applied first, followed by the `excludegeom` list. This can be used to build up the contents of a collection in pieces, or to add expression-matched geometry then remove specific unwanted matched geometries. The contents of a collection can itself be used to define a portion of another collection. The contents of each `includecollection` collection are effectively evaluated in whole before being added to the collection being built. + +If the containing file is capable of defining MaterialX-compliant collections (e.g. an Alembic or USD file), its collections can be referred to in any situation where a collection="name" reference is allowed. + + + +## Geometry Prefixes + +As a shorthand convenience, MaterialX allows the specification of a `geomprefix` attribute that will be prepended to data values of type "geomname" or "geomnamearray" (e.g. `geom` attributes in ``, ``, ``, and `` elements) specified within the scope of the element defining the `geomprefix`, similar to how MaterialX allows the specification of a `fileprefix` attribute which is prepended to input values of type "filename". For data values of type "geomnamearray", the `geomprefix` is prepended to each individual comma-separated geometry name. Since the values of the prefix and the geometry are string-concatenated, the value of a `geomprefix` should generally end with a "/". Geomprefix is commonly used to split off leading portions of geometry paths common to all geometry names, e.g. to define the "asset root" path. + +So the following MTLX file snippets are equivalent: + + +``` + + + + + + + +``` + + + +# Additional MaterialX Data Types + +Systems supporting MaterialX Geometry Extensions support the following additional standard data types: + +**GeomName** and **GeomNameArray**: attributes of type "geomname" are just strings within quotes, but specifically mean the name of a single geometry using the conventions described in the [**Geometry Representation**](#geometry-representation) and [**Geometry Name Expressions**](#geometry-name-expressions) sections. A geomname is allowed to use a geometry name expression as long as it resolves to a single geometry. Attributes of type "geomnamearray" are strings within quotes containing a comma-separated list of one or more geomname values with or without expressions, and may resolve to any number of geometries. + + +# Additional Filename Substitutions + +Filename input values for various nodes can include one or more special strings which will be replaced by the application with values derived from the current geometry, from the MaterialX state, or from the host application environment. Applications which support MaterialX Geometry Extensions also support the following filename substitution: + + +| Token | Description | +| ---- | ---- | +| <geometry token> | The value of a specified token declared in a <geominfo> element or as a uniform primvar value (generally of type string or integer) for the current geometry. | + + +Only applications fully supporting Geometry Extensions may allow using a <_geometry token_> as part of a larger filename string. All applications should allow the use of "<_geometry token_>" as the full filename string, in which case the string primvar value stored with the geometry is used as the filename unchanged; the string primvar value itself might be allowed to contain another token such as <UDIM> which the renderer may be able to parse and replace itself. + + + +# Geometry Info Elements + +Geometry Info ("geominfo") elements are used to define sets of named geometric properties with constant values, and to associate them with specific external geometries. + +The most common use for geominfo elements is to define the filenames (or portions of filenames) of texture map images mapped onto the geometry. Typically, there are several types of textures such as color, roughness, bump, opacity, etc. associated with each geometry: each texture name string would be a separate <token> within the <geominfo>. These images could contain texture data for multiple geometries, which would either be listed in the `geom` attribute of the <geominfo> element, or be assembled into a collection and the name of that collection would be specified in the `collection` attribute. + + +## GeomInfo Definition + +A **<geominfo>** element contains one or more geometry property and/or token definitions, and associates them and their values with all geometries listed in the `geom` or `collection` attribute of the <geominfo>: + +``` + + ...geometry property and token value definitions... + +``` + +Note that no two <geominfo>s may define values for the same geometry property or token for the same geometry, whether the geometry is specified directly, matched via a geometry name expression, or contained within a specified collection. + +Attributes for GeomInfo elements: + +* `name` (string, required): the unique name of the GeomInfo element +* `geom` (geomnamearray, optional): the list of geometries and/or geometry name expressions that the GeomInfo is to apply to +* `collection` (string, optional): the name of a geometric collection + +Either a `geom` or a `collection` may be specified, but not both. + + + +### GeomProp Elements + +The core MaterialX Specification defines a Geometric Property, or "geomprop", as an intrinsic or user-defined surface coordinate property of geometries referenced in a specific space and/or index, and provides several nodes to retrive the values of these properties within a shading network nodegraph, as well as a <geompropdef> element used to define the name and output type of custom geometric properties beyond the standard ones: `position`, `normal`, `tangent`, `bitangent`, `texcoord` and `geomcolor`. + +MaterialX Geometry Extensions expands upons this by allowing the use of <geomprop> elements to define specific uniform values of a geometric property with specific geometries, as opposed to relying on those values being defined externally. This could include application-specific metadata, attributes passed from a lighting package to a renderer, or other geometry-specific data. A geomprop may also specify a `unittype` and `unit` if appropriate to indicate that the geometric property's value is in that unit; see the [**Units** section of the main MaterialX Specification](./MaterialX.Specification.md#units), although typically the <geompropdef> would define the `unittype` and `unit`, and a geomprop would only provide an overriding `unit` if the unit for its value differed from the geompropdef's defined default unit. + +``` + +``` + +GeomProp elements have the following attributes: + +* `name` (string, required): the name of the geometric property to define +* `type` (string, required): the data type of the given property +* `value` (any MaterialX type, required): the value to assign to the given property. +* `unittype` (attribute, string, optional): the type of unit for this property, e.g. "distance", which must be defined by a <unittypedef>. Default is to not specify a unittype. +* `unit` (attribute, string, optional): the specific unit for this property. Default is to not specify a unit. + +Only float and vectorN geometric properties may specify a `unittype` and a `unit`. + +For example, one could specify a unique surface ID value associated with a geometry: + +``` + + + + +``` + +GeomProp values can be accessed from a nodegraph using a `` node: + +``` + +``` + +A <geomprop> can also be used to define a default value for an intrinsic varying geometric property such as "geomcolor" for the geometry specified by the enclosing <geominfo>, which would be returned by the corresponding Geometric node (e.g. <geomcolor>) if the current geometry did not itself define values for that property. + +``` + + + +``` + + + +### Geometry Token Elements + +Token elements may be used within <geominfo> elements to define constant (typically string or integer) named values associated with specific geometries. These geometry token values can be substituted into filenames within image nodes; see the [**Additional Filename Substitutions**](#additional-filename-substitutions) section above for details: + +``` + +``` + +The "value" can be any MaterialX type, but since tokens are used in filename substitutions, string and integer values are recommended. + +Token elements have the following attributes: + +* `name` (string, required): the name of the geometry token to define +* `type` (string, required): the geometry token's type +* `value` (any MaterialX type, optional): the value to assign to that token name for this geometry. + +For example, one could specify a texture identifier value associated with a geometry: + +``` + + + +``` + +and then reference that token's value in a filename: + +``` + + + +``` + +The <txtid> in the file name would be replaced by whatever value the txtid token had for each geometry. + + +### TokenDefault Elements + +TokenDefault elements define the default value for a specified geometry token name; this default value will be used in a filename string substitution if an explicit token value is not defined for the current geometry. Since TokenDefault does not apply to any geometry in particular, it must be used outside of a <geominfo> element. + +``` + +``` + + +### Reserved GeomProp Names + +Workflows involving textures with implicitly-computed filenames based on u,v coordinates (such as <UDIM> and <UVTILE>) can be made more efficient by explicitly listing the set of values that they resolve to for any given geometry. The MaterialX specification reserves two geomprop names for this purpose, `udimset` and `uvtileset`, each of which is a stringarray containing a comma-separated list of UDIM or UVTILE values: + +``` + + + + + + + +``` + + + +# Look and Property Elements + +**Look** elements define the assignments of materials, visibility and other properties to geometries and geometry collections. In MaterialX, a number of geometries are associated with each stated material, visibility type or property in a look, as opposed to defining the particular material or properties for each geometry. + +**Property** elements define non-material properties that can be assigned to geometries or collections in Looks. There are a number of standard MaterialX property types that can be applied universally for any rendering target, as well as a mechanism to define target-specific properties for geometries or collections. + +A MaterialX document can contain multiple property and/or look elements. + + +## Property Definition + +A **<property>** element defines the name, type and value of a look-specific non-material property of geometry; <**propertyset**> elements are used to group a number of <property>s into a single named object. The connection between properties or propertysets and specific geometries or collections is done in a <look> element, so that these properties can be reused across different geometries, and enabled in some looks but not others. <Property> elements may only be used within <propertyset>s; they may not be used independently, although a dedicated <propertyassign> element may be used within a <look> to declare a property name, type, value and assignment all at once. + +``` + + + + +``` + +The following properties are considered standard in MaterialX, and should be respected on all platforms that support these concepts: + + +| Property | Type | Default Value | +| --- | --- | --- | +| **`twosided`** | boolean | false | +| **`matte`** | boolean | false | + +where `twosided` means the geometry should be rendered even if the surface normal faces away from camera, and `matte` means the geometry should hold out, or "matte" out anything behind it (including in the alpha channel). + +In the example above, the "trace_maxdiffusedepth" property is target-specific, having been restricted to the context of Renderman RIS by setting its `target` attribute to “rmanris”. + + + +## Look Definition + +A **<look>** element contains one or more material, variant, visibility and/or propertyset assignment declarations: + +``` + + ...materialassign, variantassign, visibilityassign, property/propertysetassign declarations... + +``` + +Looks can inherit the assignments from another look by including an `inherit` attribute. The look can then specify additional assignments that will apply on top of/in place of whatever came from the source look. This is useful for defining a base look and then one or more "variation" looks. It is permissible for an inherited-from look to itself inherit from another look, but a look can inherit from only one parent look. + +A number of looks can be grouped together into a **LookGroup**, e.g. to indicate which looks are defined for a particular asset: + +``` + +``` + +where `lookgroupname` is the name of the lookgroup being defined, `look1`/`look2`/etc. are the names of <look> or <lookgroup> elements to be contained in the lookgroup (a lookgroup name would resolve to the set of looks recursively contained in that lookgroup), and `default` (if specified) specifies the name of one of the looks defined in `looks` to be the default look to use. A look can be contained in any number of lookgroups. + +<Look> and <lookgroup> elements also support other attributes such as `xpos`, `ypos` and `uicolor` as described in the Standard UI Attributes section above. + + +## Assignment Elements + +Various types of assignment elements are used within looks to assign materials, categorized visibility and properties to specific geometries, or variants to materials. + +For elements which make assignments to geometries, the pathed names within `geom` attributes or stored within collections do not need to resolve strictly to "leaf" path locations or actual renderable geometry names: assignments can also be made to intermediate "branch" geometry path locations, which will then apply to any geometry at a deeper level in the path hierarchy which does not have another "closer to the leaf" level assignment. E.g. an assignment to "/a/b/c" will effectively apply to "/a/b/c/d" and "/a/b/c/foo/bar" (and anything else whose full path name begins with "/a/b/c/") if no other assignment is made to "/a/b/c/d", "/a/b/c/foo", or "/a/b/c/foo/bar". If a look inherits from another look, the child look can replace assignments made to any specific path location (e.g. a child assignment to "/a/b/c" would take precedence over a parent look's assignment to "/a/b/c"), but an assignment by the parent look to a more "leaf"-level path location would take precedence over a child look assignment to a higher "branch"-level location. + + +### MaterialAssign Elements + +MaterialAssign elements are used within a <look> to connect a specified material to one or more geometries or collections (either a `geom` or a `collection` may be specified, but not both). + +``` + + ...optional variantassign elements... + +``` + +Material assignments are generally assumed to be mutually-exclusive, that is, any individual geometry is assigned to only one material. Therefore, assign declarations should be processed in the order they appear in the file, and if any geometry appears in multiple <materialassign>s, the last <materialassign> wins. However, some applications allow multiple materials to be assigned to the same geometry as long as the shader node types don't overlap. If the `exclusive` attribute is set to false (default is true), then earlier material assigns will still take effect for all shader node types not defined in the materials of later assigns: for each shader node type, the shader within the last assigned material referencing a matching shader node type wins. If a particular application does not support multiple material assignments to the same geometry, the value of `exclusive` is ignored and only the last full material and its shaders are assigned to the geometry, and the parser should issue a warning. + + +### VariantAssign Elements + +VariantAssign elements are used within a <materialassign> or a <look> to apply the values defined in one variant of a variantset to one assigned material, or to all applicable materials in a look. + +``` + + + + + + + ... + +``` + +VariantAssign elements have the following attributes: + +* `name` (string, required): the unique name of the VariantAssign element +* `variantset` (string, required): the name of the variantset to apply the variant from +* `variant` (string, required): the name of the variant within `variantset` to use + +In the above example, the input/token values defined within variant "var1" will be applied to and and all identically-named inputs/tokens found in either "material1" or "material2" unless restricted by a `node` or `nodedef` attribute defined in the <variantset>, while values defined within variant "var2" will only be applied to matching-named bindings in "material1". VariantAssigns are applied in the order specified within a scope, with those within a <materialassign> taking precedence over those which are direct children of the <look>. + + +### Visibility Elements + +Visibility elements are used within a <look> to define various types of generalized visibility between a "viewer" object and other geometries. A "viewer object" is simply a geometry that has the ability to "see" other geometries in some rendering context and thus may need to have the list of geometries that it "sees" in different contexts be specified; the most common examples are light sources and a primary rendering camera. + +``` + +``` + +Visibility elements have the following attributes: + +* `name` (string, required): the unique name of the Visibility element +* `viewergeom` (geomnamearray, optional): the list of viewer geometry objects that the <visibility> assignment affects +* `viewercollection` (string, optional): the name of a collection containing viewer geometry objects that the <visibility> assignment affects +* `geom` (geomnamearray, optional): the list of geometries and/or geometry name expressions that the `viewergeom` object should (or shouldn't) "see" +* `collection` (string, optional): the name of a defined collection of geometries that the `viewergeom` object should (or shouldn't) "see" +* `vistype` (string, optional): the type of visibility being defined; see table below +* `visible` (boolean, optional): if false, the geom/collection objects will be invisible to this particular type of visibility; defaults to "true". + +The `viewergeom` attribute (and/or the contents of a collection referred to by the `viewercollection` attribute) typically refers to the name of a light (or list of lights) or other "geometry viewing" object(s). If `viewergeom`/`viewercollection` are omitted, the visibility applies to all applicable viewers (camera, light, geometry) within the given render context; `viewergeom`/`viewercollection` are not typically specified for `vistype` "camera". Either `geom` or `collection` must be defined but not both; similarly, one cannot define both a `viewergeom` and a `viewercollection`. + +The `vistype` attribute refers to a specific type of visibility. If a particular `vistype` is not assigned within a <look>, then all geometry is visible by default to all `viewergeom`s for that `vistype`; this means that to have only a certain subset of geometries be visible (either overall or to a particular `vistype`), it is necessary to first assign <visibility> with `visible="false"` to all geometry. Additional <visibility> assignments to the same `vistype` within a <look> are applied on top of the current visibility state. The following `vistype`s are predefined by MaterialX; applications are free to define additional `vistype`s: + + +| Vistype | Description | +| --- | --- | +| **`camera`** | camera or "primary" ray visibility | +| **`illumination`** | geom or collection is illuminated by the viewergeom light(s) | +| **`shadow`** | geom or collection casts shadows from the viewergeom light(s) | +| **`secondary`** | indirect/bounce ray visibility of geom or collection to viewergeom geometry | + + +If `vistype` is not specified, then the visibility assignment applies to _all_ visibility types, and in fact will take precedence over any specific `vistype` setting on the same geometry: geometry assigned a <`visibility>` with no `vistype` and `visible="false"` will not be visible to camera, shadows, secondary rays, or any other ray or render type. This mechanism can be used to cleanly hide geometry not needed in certain variations of an asset, e.g. different costume pieces or alternate damage shapes. + +If the <visibility> `geom` or `collection` refers to light geometry, then assigning `vistype="camera"` determines whether or not the light object itself is visible to the camera/viewer (e.g. "do you see the bulb"), while assigning `visible="false"` with no `vistype` will mute the light so it is neither visible to camera nor emitting any light. + +For the "secondary" vistype, `viewergeom` should be renderable geometry rather than a light, to declare that certain other geometry is or is not visible to indirect bounce illumination or raytraced reflections in that `viewergeom`. In this example, "/b" would not be seen in reflections nor contribute indirect bounce illumination to "/a", while geometry "/c" would not be visible to _any_ secondary rays: + +``` + + +``` + + +### PropertyAssign Elements + +PropertyAssign and PropertySetAssign elements are used within a <look> to connect a specified property value or propertyset to one or more geometries or collections. + +``` + + +``` + +Either a `geom` or a `collection` may be specified, but not both. Multiple property/propertyset assignments can be made to the same geometry or collection, as long as no conflicting assignment is made. If there are any conflicting assignments, it is up to the host application to determine how such conflicts are to be resolved, but host applications should apply property assignments in the order they are listed in the look, so it should generally be safe to assume that if two property/propertyset assignments set different values for the same property to the same geometry, the later assignment will win. + + +## Look Examples + +This example defines four collections, a light shader and material, and a propertyset, which are then used by two looks: + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + +# References + +[^1]: + diff --git a/documents/Specification/inprog_v1.39/MaterialX.PBRSpec.md b/documents/Specification/inprog_v1.39/MaterialX.PBRSpec.md new file mode 100644 index 0000000000..58138c8308 --- /dev/null +++ b/documents/Specification/inprog_v1.39/MaterialX.PBRSpec.md @@ -0,0 +1,463 @@ + + + +# MaterialX Physically Based Shading Nodes + +**Version 1.39** +Niklas Harrysson - Lumiere Software +Doug Smythe - Industrial Light & Magic +Jonathan Stone - Lucasfilm Advanced Development Group +April 7, 2022 + +# Introduction + +The [**MaterialX Specification**](./MaterialX.Specification.md) describes a number of standard nodes that may be used to construct node graphs for the processing of images, procedurally-generated values, coordinates and other data. With the addition of user-defined custom nodes, it is possible to describe complete rendering shaders using node graphs. Up to this point, there has been no standardization of the specific shader-semantic nodes used in these node graph shaders, although with the widespread shift toward physically-based shading, it appears that the industry is settling upon a number of specific BSDF and other functions with standardized parameters and functionality. + +This document describes a number of shader-semantic nodes implementing widely-used surface scattering, emission and volume distribution functions and utility nodes useful in constructing complex layered rendering shaders using node graphs. These nodes in combination with other nodes may be used with the MaterialX shader generation (ShaderGen[^1]) system. + + +## Table of Contents + +**[Physical Material Model](#physical-material-model)** + [Scope](#scope) + [Physically Plausible Materials](#physically-plausible-materials) + [Quantities and Units](#quantities-and-units) + [Color Management](#color-management) + [Surfaces](#surfaces) +  [Layering](#layering) +  [Bump and Normal Mapping](#bump-and-normal-mapping) +  [Surface Thickness](#surface-thickness) + [Volumes](#volumes) + [Lights](#lights) + +**[MaterialX PBS Library](#materialx-pbs-library)** + [Data Types](#data-types) + [BSDF Nodes](#bsdf-nodes) + [EDF Nodes](#edf-nodes) + [VDF Nodes](#vdf-nodes) + [Shader Nodes](#shader-nodes) + [Utility Nodes](#utility-nodes) + +**[Shading Model Examples](#shading-model-examples)** + [Autodesk Standard Surface](#autodesk-standard-surface) + [UsdPreviewSurface](#usdpreviewsurface) + +**[References](#references)** + + + +# Physical Material Model + +This section describes the material model used in the MaterialX Physically Based Shading (PBS) library and the rules we must follow to be physically plausible. + + +## Scope + +A material describes the properties of a surface or medium that involves how it reacts to light. To be efficient, a material model is split into different parts, where each part handles a specific type of light interaction: light being scattered at the surface, light being emitted from a surface, light being scattered inside a medium, etc. The goal of our material model definition is to describe light-material interactions typical for physically plausible rendering systems, including those in feature film production, real-time preview, and game engines. + +Our model has support for surface materials, which includes scattering and emission of light from the surface of objects, and volume materials, which includes scattering and emission of light within a participating medium. For lighting, we support local lights and distant light from environments. Geometric modification is supported in the form of bump and normal mapping as well as displacement mapping. + + +## Physically Plausible Materials + +The initial requirements for a physically-plausible material are that it 1) should be energy conserving and 2) support reciprocity. The energy conserving says that the sum of reflected and transmitted light leaving a surface must be less than or equal to the amount of light reaching it. The reciprocity requirement says that if the direction of the traveling light is reversed, the response from the material remains unchanged. That is, the response is identical if the incoming and outgoing directions are swapped. All materials implemented for ShaderGen should respect these requirements and only in rare cases deviate from it when it makes sense for the purpose of artistic freedom. + + +## Quantities and Units + +Radiometric quantities are used by the material model for interactions with the renderer. The fundamental radiometric quantity is **radiance** (measured in _Wm−2sr−1_) and gives the intensity of light arriving at, or leaving from, a given point in a given direction. If incident radiance is integrated over all directions we get **irradiance** (measured in _Wm−2_), and if we integrate this over surface area we get **power** (measured in _W_). Input parameters for materials and lights specified in photometric units can be suitably converted to their radiometric counterparts before being submitted to the renderer. + +The interpretation of the data types returned by surface and volume shaders are unspecified, and left to the renderer and the shader generator for that renderer to decide. For an OpenGL-type renderer they will be tuples of floats containing radiance calculated directly by the shader node, but for an OSL-type renderer they may be closure primitives that are used by the renderer in the light transport simulation. + +In general, a color given as input to the renderer is considered to represent a linear RGB color space. However, there is nothing stopping a renderer from interpreting the color type differently, for instance to hold spectral values. In that case, the shader generator for that renderer needs to handle this in the implementation of the nodes involving the color type. + + +## Color Management + +MaterialX supports the use of [color management systems](./MaterialX.Specification.md#color-spaces-and-color-management-systems) to associate colors with specific color spaces. A MaterialX document typically specifies the working color space that is to be used for the document as well as the color space in which input values and textures are given. If these color spaces are different from the working color space, it is the application's and shader generator's responsibility to transform them. + +The ShaderGen module has an interface that can be used to integrate support for different color management systems. A simplified implementation with some popular and commonly used color transformations is supplied and enabled by default. A full integration of OpenColorIO ([http://opencolorio.org](http://opencolorio.org)) is planned for the future. + + +## Surfaces + +In our surface shading model the scattering and emission of light is controlled by distribution functions. Incident light can be reflected off, transmitted through, or absorbed by a surface. This is represented by a Bidirectional Scattering Distribution Function (BSDF). Light can also be emitted from a surface, for instance from a light source or glowing material. This is represented by an Emission Distribution Function (EDF). The PBS library introduces the [data types](#data-types) `BSDF` and `EDF` to represent the distribution functions, and there are nodes for constructing, combining and manipulating them. + +![Physically Based Shading Diagram](media/PBSdiagram.png "Physically Based Shading Diagram") + +Another important property is the **index of refraction** (IOR), which describes how light is propagated through a medium. It controls how much a light ray is bent when crossing the interface between two media of different refractive indices. It also determines the amount of light that is reflected and transmitted when reaching the interface, as described by the Fresnel equations. + +A surface shader is represented with the data type `surfaceshader`. In the PBS library there is a [<surface> node](#node-surface) that constructs a surface shader from a BSDF and an EDF. Since there are nodes to combine and modify them, you can easily build surface shaders from different combinations of distribution functions. Inputs on the distribution function nodes can be connected, and nodes from the standard library can be combined into complex calculations, giving flexibility for the artist to author material variations over the surfaces. + +It is common for shading models to differentiate between closed surfaces and thin-walled surfaces. A closed surface represents a closed watertight interface with a solid interior. A typical example is a solid glass object. A thin-walled surface on the other hand has an infinitely thin volume, as with a sheet of paper or a soap bubble. For a closed surface there can be no backside visible if the material is opaque. In the case of a transparent closed surface a backside hit is treated as light exiting the closed interface. For a thin-walled surface both the front and back side are visible and it can either have the same material on both sides or different materials on each side. If the material is transparent in this case the thin wall makes the light transmit without refraction or scattering. By default the [<surface> node](#node-surface) constructs a surface shader for a closed surface, but there is a boolean switch to make it thin-walled. + +In order to assign different shaders to each side of a thin-walled object the [<surfacematerial> node](./MaterialX.Specification.md#node-surfacematerial) in the standard library has an input to connect an extra backside surface shader. If any of the sides of a <surfacematerial> has a thin-walled shader connected, both sides are considered to be thin-walled. Hence the thin-walled property takes precedence to avoid ambiguity between the sides. If only one side has a shader connected this is used for both sides. If both sides are connected but none of the shaders are thin-walled the front shader is used. The thin-walled property also takes precedence in the case of mixing surface shaders. If any of the shaders involved in the mix is thin-walled, both shaders are considered to be thin-walled. + +Note that in order to have surface shaders set for both sides the geometry has to be set as double-sided. Geometry sidedness is a property not handled by MaterialX and needs to be set elsewhere. + + +### Layering + +In order to simplify authoring of complex materials, our model supports the notion of layering. Typical examples include: adding a layer of clear coat over a car paint material, or putting a layer of dirt or rust over a metal surface. Layering can be done in a number of different ways: + + + +* Horizontal Layering: A simple way of layering is using per-shading-point linear mixing of different BSDFs where a mix factor is given per BSDF controlling its contribution. Since the weight is calculated per shading point it can be used as a mask to hide contributions on different parts of a surface. The weight can also be calculated dependent on view angle to simulate approximate Fresnel behavior. This type of layering can be done both on a BSDF level and on a surface shader level. The latter is useful for mixing complete shaders which internally contain many BSDFs, e.g. to put dirt over a car paint, grease over a rusty metal or adding decals to a plastic surface. We refer to this type of layering as **horizontal layering** and the [<mix> node](#node-mix) in the PBS library can be used to achieve this (see below). +* Vertical Layering: A more physically correct form of layering is also supported where a top BSDF layer is placed over another base BSDF layer, and the light not reflected by the top layer is assumed to be transmitted to the base layer; for example, adding a dielectric coating layer over a substrate. The refraction index and roughness of the coating will then affect the attenuation of light reaching the substrate. The substrate can be a transmissive BSDF to transmit the light further, or a reflective BSDF to reflect the light back up through the coating. The substrate can in turn be a reflective BSDF to simulate multiple specular lobes. We refer to this type of layering as **vertical layering** and it can be achieved using the [<layer> node](#node-layer) in the PBS library. See [<dielectric_bsdf>](#node-dielectric-bsdf), [<sheen_bsdf>](#node-sheen-bsdf) and [<thin_film_bsdf>](#node-thin-film-bsdf) below. +* Shader Input Blending: Calculating and blending many BSDFs or separate surface shaders can be expensive. In some situations good results can be achieved by blending the texture/value inputs instead, before any illumination calculations. Typically one would use this with an über-shader that can simulate many different materials, and by masking or blending its inputs over the surface you get the appearance of having multiple layers, but with less expensive texture or value blending. Examples of this are given in the main [MaterialX Specification "Pre-Shader Compositing Example"](./MaterialX.Specification.md#example-pre-shader-compositing-material). + + +### Bump and Normal Mapping + +The surface normal used for shading calculations is supplied as input to each BSDF that requires it. The normal can be perturbed by bump or normal mapping, before it is given to the BSDF. As a result, one can supply different normals for different BSDFs for the same shading point. When layering BSDFs, each layer can use different bump and normal maps. + + +## Volumes + +In our volume shader model the scattering of light in a participating medium is controlled by a volume distribution function (VDF), with coefficients controlling the rate of absorption and scattering. The VDF represents what physicists call a _phase function, _describing how the light is distributed from its current direction when it is scattered in the medium. This is analogous to how a BSDF describes scattering at a surface, but with one important difference: a VDF is normalized, summing to 1.0 if all directions are considered. Additionally, the amount of absorption and scattering is controlled by coefficients that gives the rate (probability) per distance traveled in world space. The **absorption coefficient** sets the rate of absorption for light traveling through the medium, and the **scattering coefficient** sets the rate of which the light is scattered from its current direction. The unit for these are _m−1_. + +Light can also be emitted from a volume. This is represented by an EDF analog to emission from surfaces, but in this context the emission is given as radiance per distance traveled through the medium. The unit for this is _Wm−3sr−1_. The emission distribution is oriented along the current direction. + +The [<volume> node](#node-volume) in the PBS library constructs a volume shader from individual VDF and EDF components. There are also nodes to construct various VDFs, as well as nodes to combine them to build more complex ones. + +VDFs can also be used to describe the interior of a surface. A typical example would be to model how light is absorbed or scattered when transmitted through colored glass or turbid water. This is done by layering a BSDF for the surface transmission over the VDF using a [<layer> node](#node-layer). + + +## Lights + +Light sources can be divided into environment lights and local lights. Environment lights represent contributions coming from infinitely far away. All other lights are local lights and have a position and extent in space. + +Local lights are specified as light shaders assigned to a locator, modeling an explicit light source, or in the form of emissive geometry using an emissive surface shader. The [<light> node](#node-light) in the PBS library constructs a light shader from an EDF. There are also nodes to construct various EDFs as well as nodes to combine them to build more complex ones. Emissive properties of surface shaders are also modelled using EDFs; see the [**EDF Nodes**](#edf-nodes) section below for more information. + +Light contributions coming from far away are handled by environment lights. These are typically photographically-captured or procedurally-generated images that surround the whole scene. This category of lights also includes sources like the sun, where the long distance traveled makes the light essentially directional and without falloff. For all shading points, an environment is seen as being infinitely far away. + + + +# MaterialX PBS Library + +MaterialX includes a library of types and nodes for creating physically plausible materials and lights as described above. This section outlines the content of that library. + + +## Data Types + +* `BSDF`: Data type representing a Bidirectional Scattering Distribution Function. +* `EDF`: Data type representing an Emission Distribution Function. +* `VDF`: Data type representing a Volume Distribution Function. + +The PBS nodes also make use of the following standard MaterialX types: + +* `surfaceshader`: Data type representing a surface shader. +* `lightshader`: Data type representing a light shader. +* `volumeshader`: Data type representing a volume shader. +* `displacementshader`: Data type representing a displacement shader. + + +## BSDF Nodes + + + +* **`oren_nayar_diffuse_bsdf`**: Constructs a diffuse reflection BSDF based on the Oren-Nayar reflectance model[^2]. A roughness of 0.0 gives Lambertian reflectance. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color` (color3): Diffuse reflectivity (albedo). Defaults to (0.18, 0.18, 0.18). + * `roughness `(float): Surface roughness, range [0.0, 1.0]. Defaults to 0.0. + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + + + +* **`burley_diffuse_bsdf`**: Constructs a diffuse reflection BSDF based on the corresponding component of the Disney Principled model[^3]. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color` (color3): Diffuse reflectivity (albedo). Defaults to (0.18, 0.18, 0.18). + * `roughness` (float): Surface roughness, range [0.0, 1.0]. Defaults to 0.0. + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + + + +* **`dielectric_bsdf`**: Constructs a reflection and/or transmission BSDF based on a microfacet reflectance model and a Fresnel curve for dielectrics[^4]. If reflection scattering is enabled the node may be layered vertically over a base BSDF for the surface beneath the dielectric layer. By chaining multiple <dielectric_bsdf> nodes you can describe a surface with multiple specular lobes. If transmission scattering is enabled the node may be layered over a VDF describing the surface interior to handle absorption and scattering inside the medium, useful for colored glass, turbid water, etc. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `tint` (color3): Color weight to tint the reflected and transmitted light. Defaults to (1.0, 1.0, 1.0). Note that changing the tint gives non-physical results and should only be done when needed for artistic purposes. + * `ior` (float): Index of refraction of the surface. Defaults to 1.5. If set to 0.0 the Fresnel curve is disabled and reflectivity is controlled only by weight and tint. + * `roughness` (vector2): Surface roughness. Defaults to (0.05, 0.05). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + * `tangent` (vector3): Tangent vector of the surface. Defaults to world space tangent. + * `distribution` (uniform string): Microfacet distribution type. Defaults to "ggx". + * `scatter_mode` (uniform string): Scattering mode, specifying whether the BSDF supports reflection "R", transmission "T" or both reflection and transmission "RT". With "RT", reflection and transmission occur both when entering and leaving a surface, with their respective intensities controlled by the Fresnel curve. Depending on the IOR and incident angle, it is possible for total internal reflection to occur, generating no transmission even if "T" or "RT" is selected. Defaults to "R". + + + +* **`conductor_bsdf`**: Constructs a reflection BSDF based on a microfacet reflectance model[^5]. Uses a Fresnel curve with complex refraction index for conductors/metals. If an artistic parametrization[^6] is needed the [<artistic_ior> utility node](#node-artistic-ior) can be connected to handle this. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `ior `(color3): Index of refraction. Default is (0.18, 0.42, 1.37) with colorspace "none" (approximate IOR for gold). + * `extinction` (color3): Extinction coefficient. Default is (3.42, 2.35, 1.77) with colorspace "none" (approximate extinction coefficients for gold). + * `roughness` (vector2): Surface roughness. Defaults to (0.05, 0.05). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + * `tangent` (vector3): Tangent vector of the surface. Defaults to world space tangent. + * `distribution` (uniform string): Microfacet distribution type. Defaults to "ggx". + + + +* **`generalized_schlick_bsdf`**: Constructs a reflection and/or transmission BSDF based on a microfacet model and a generalized Schlick Fresnel curve[^7]. If reflection scattering is enabled the node may be layered vertically over a base BSDF for the surface beneath the dielectric layer. By chaining multiple <generalized_schlick_bsdf> nodes you can describe a surface with multiple specular lobes. If transmission scattering is enabled the node may be layered over a VDF describing the surface interior to handle absorption and scattering inside the medium, useful for colored glass, turbid water, etc. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color0` (color3): Reflectivity per color component at facing angles. Defaults to (1.0, 1.0, 1.0). + * `color90` (color3): Reflectivity per color component at grazing angles. Defaults to (1.0, 1.0, 1.0). + * `exponent` (float): Exponent for the Schlick blending between `color0` and `color90`. Defaults to 5.0. + * `roughness` (vector2): Surface roughness. Defaults to (0.05, 0.05). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + * `tangent` (vector3): Tangent vector of the surface. Defaults to world space tangent. + * `distribution` (uniform string): Microfacet distribution type. Defaults to "ggx". + * `scatter_mode` (uniform string): Scattering mode, specifying whether the BSDF supports reflection "R", transmission "T" or both reflection and transmission "RT". With "RT", reflection and transmission occur both when entering and leaving a surface, with their respective intensities controlled by the Fresnel curve. Depending on the IOR and incident angle, it is possible for total internal reflection to occur, generating no transmission even if "T" or "RT" is selected. Defaults to "R". + + + +* **`translucent_bsdf`**: Constructs a translucent (diffuse transmission) BSDF based on the Lambert reflectance model. + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color` (color3): Diffuse transmittance. Defaults to (1.0, 1.0, 1.0). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + + + +* **`subsurface_bsdf`**: Constructs a subsurface scattering BSDF for subsurface scattering within a homogeneous medium. The parameterization is chosen to match random walk Monte Carlo methods as well as approximate empirical methods[^8]. Note that this category of subsurface scattering can be defined more rigorously as a BSDF vertically layered over an [](#node-anisotropic-vdf), and we expect these two descriptions of the scattering-surface distribution function to be unified in future versions of MaterialX. + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color` (color3): Diffuse reflectivity (albedo). Defaults to (0.18, 0.18, 0.18). + * `radius` (color3): Sets the average distance that light might propagate below the surface before scattering back out. This is also known as the mean free path of the material. The radius can be set for each color component separately. Default is (1, 1, 1). + * `anisotropy` (float): Anisotropy factor, controlling the scattering direction, range [-1.0, 1.0]. Negative values give backwards scattering, positive values give forward scattering, and a value of zero gives uniform scattering. Defaults to 0.0. + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + + + +* **`sheen_bsdf`**: Constructs a microfacet BSDF for the back-scattering properties of cloth-like materials. This node may be layered vertically over a base BSDF using a [<layer> node](#node-layer). All energy that is not reflected will be transmitted to the base layer[^9]. + + + * `weight` (float): Weight for this BSDF’s contribution, range [0.0, 1.0]. Defaults to 1.0. + * `color` (color3): Sheen reflectivity. Defaults to (1.0, 1.0, 1.0). + * `roughness` (float): Surface roughness, range [0.0, 1.0]. Defaults to 0.3. + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + + + +* **`thin_film_bsdf`**: Adds an iridescent thin film layer over a microfacet base BSDF[^10]. The thin film node must be layered over the base BSDF using a [<layer> node](#node-layer), as the node is a modifier and cannot be used as a standalone BSDF. + + + * `thickness` (float): Thickness of the thin film layer in nanometers. Default is 550 nm. + * `ior` (float): Index of refraction of the thin film layer. Default is 1.5. + + +## EDF Nodes + + + +* **`uniform_edf`**: Constructs an EDF emitting light uniformly in all directions. + * `color` (color3): Radiant emittance of light leaving the surface. Default is (1, 1, 1). + + + +* **`conical_edf`**: Constructs an EDF emitting light inside a cone around the normal direction. + * `color` (color3): Radiant emittance of light leaving the surface. Default is (1, 1, 1). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + * `inner_angle` (uniform float): Angle of inner cone where intensity falloff starts (given in degrees). Defaults to 60. + * `outer_angle` (uniform float): Angle of outer cone where intensity goes to zero (given in degrees). If set to a smaller value than inner angle no falloff will occur within the cone. Defaults to 0. + + + +* **`measured_edf`**: Constructs an EDF emitting light according to a measured IES light profile[^11]. + + + * `color` (color3): Radiant emittance of light leaving the surface. Default is (1, 1, 1). + * `normal` (vector3): Normal vector of the surface. Defaults to world space normal. + * `file` (uniform filename): Path to a file containing IES light profile data. Default is "". + + + +* **`generalized_schlick_edf`**: Adds a directionally varying factor to an EDF. Scales the emission distribution of the base EDF according to a generalized Schlick Fresnel curve. + * `color0` (color3): Scale factor for emittance at facing angles. Default is (1, 1, 1). + * `color90` (color3): Scale factor for emittance at grazing angles. Default is (1, 1, 1). + * `exponent` (float): Exponent for the Schlick blending between `color0` and `color90`. Defaults to 5.0. + * `base` (EDF): The base EDF to be modified. Defaults to "". + + +## VDF Nodes + + + +* **`absorption_vdf`**: Constructs a VDF for pure light absorption. + * `absorption` (color3): Absorption rate for the medium (rate per distance traveled in the medium, given in _m−1_). Set for each color component/wavelength separately. Default is (0, 0, 0). + + + +* **`anisotropic_vdf`**: Constructs a VDF scattering light for a participating medium, based on the Henyey-Greenstein phase function[^12]. Forward, backward and uniform scattering is supported and controlled by the anisotropy input. + + * `absorption` (color3): Absorption rate for the medium (rate per distance traveled in the medium, given in _m−1_). Set for each color component/wavelength separately. Default is (0, 0, 0). + * `scattering` (color3): Scattering rate for the medium (rate per distance traveled in the medium, given in _m−1_). Set for each color component/wavelength separately. Default is (0, 0, 0). + * `anisotropy` (float): Anisotropy factor, controlling the scattering direction, range [-1.0, 1.0]. Negative values give backwards scattering, positive values give forward scattering, and a value of 0.0 (the default) gives uniform scattering. + + +## Shader Nodes + + + +* **`surface`**: Constructs a surface shader describing light scattering and emission for surfaces. By default the node will construct a shader for a closed surface, representing an interface to a solid volume. In this mode refraction and scattering is enabled for any transmissive BSDFs connected to this surface. By setting thin_walled to "true" the node will instead construct a thin-walled surface, representing a surface with an infinitely thin volume. In thin-walled mode refraction and scattering will be disabled. Thin-walled mode must be enabled to construct a double-sided material with different surface shaders on the front and back side of geometry (using [<surfacematerial>](./MaterialX.Specification.md#node-surfacematerial) in the standard library). Output type "surfaceshader". + * `bsdf` (BSDF): Bidirectional scattering distribution function for the surface. Default is "". + * `edf` (EDF): Emission distribution function for the surface. If unconnected, then no emission will occur. + * `opacity` (float): Cutout opacity for the surface. Defaults to 1.0. + * `thin_walled` (boolean): Set to "true" to make the surface thin-walled. Default is "false". + + + +* **`volume`**: Constructs a volume shader describing a participating medium. Output type "volumeshader". + * `vdf` (VDF): Volume distribution function for the medium. Default is "". + * `edf` (EDF): Emission distribution function for the medium. If unconnected, then no emission will occur. + + + +* **`light`**: Constructs a light shader describing an explicit light source. The light shader will emit light according to the connected EDF. If the shader is attached to geometry both sides will be considered for light emission and the EDF controls if light is emitted from both sides or not. Output type "lightshader". + * `edf` (EDF): Emission distribution function for the light source. Default is no emission. + * `intensity` (color3): Intensity multiplier for the EDF’s emittance. Defaults to (1.0, 1.0, 1.0). + * `exposure` (float): Exposure control for the EDF’s emittance. Defaults to 0.0. + + + +* **`environment`**: Constructs a light shader describing an environment or IBL light source. The light shader will emit light coming from all directions according to the specified lat/long environment image file, in which the bottom edge is the "downward" direction, the top edge is the "upward" direction, and the left/right edge "seam" in the environment image is aligned with the "toward camera" axis. E.g. in applications where +Y is "up" and +Z is "toward camera", latitudes -pi/2 and +pi/2 correspond to the negative and positive y direction; latitude 0, longitude 0 points into positive z direction; and latitude 0, longitude pi/2 points into positive x direction. Output type "lightshader". + * `in` (color3): the latlong environment/IBL texture for the light source. Defaults to (0,0,0), producing no emission. + * `space` (uniform string): the space in which the environment is defined, defaults to "world". + * `intensity` (color3): Intensity multiplier for the light's emittance. Defaults to (1.0, 1.0, 1.0). + * `exposure` (float): Exposure control for the light's emittance. Defaults to 0.0. + + +## Utility Nodes + + + +* **`mix`**: Mix two same-type distribution functions according to a weight. Performs horizontal layering by linear interpolation between the two inputs, using the function "bg∗(1−mix) + fg∗mix". + * `bg` (BSDF or EDF or VDF): The first distribution function. Defaults to "". + * `fg` (same type as `bg`): The second distribution function. Defaults to "". + * `mix` (float): The mixing weight, range [0.0, 1.0]. Default is 0. + + + +* **`layer`**: Vertically layer a layerable BSDF such as [<dielectric_bsdf>](#node-dielectric-bsdf), [<generalized_schlick_bsdf>](#node-generalized-schlick-bsdf), [<sheen_bsdf>](#node-sheen-bsdf) or [<thin_film_bsdf>](#node-thin-film-bsdf) over a BSDF or VDF. The implementation is target specific, but a standard way of handling this is by albedo scaling, using the function "base*(1-reflectance(top)) + top", where the reflectance function calculates the directional albedo of a given BSDF. + * `top` (BSDF): The top BSDF. Defaults to "". + * `base` (BSDF or VDF): The base BSDF or VDF. Defaults to "". + + + +* **`add`**: Additively blend two distribution functions of the same type. + * `in1` (BSDF or EDF or VDF): The first distribution function. Defaults to "". + * `in2` (same type as `in1`): The second distribution function. Defaults to "". + + + +* **`multiply`**: Multiply the contribution of a distribution function by a scaling weight. The weight is either a float to attenuate the channels uniformly, or a color which can attenuate the channels separately. To be energy conserving the scaling weight should be no more than 1.0 in any channel. + * `in1` (BSDF or EDF or VDF): The distribution function to scale. Defaults to "". + * `in2` (float or color3): The scaling weight. Default is 1.0. + + + +* **`roughness_anisotropy`**: Calculates anisotropic surface roughness from a scalar roughness and anisotropy parameterization. An anisotropy value above 0.0 stretches the roughness in the direction of the surface's "tangent" vector. An anisotropy value of 0.0 gives isotropic roughness. The roughness value is squared to achieve a more linear roughness look over the input range [0,1]. Output type "vector2". + * `roughness` (float): Roughness value, range [0.0, 1.0]. Defaults to 0.0. + * `anisotropy` (float): Amount of anisotropy, range [0.0, 1.0]. Defaults to 0.0. + + + +* **`roughness_dual`**: Calculates anisotropic surface roughness from a dual surface roughness parameterization. The roughness is squared to achieve a more linear roughness look over the input range [0,1]. Output type "vector2". + * `roughness` (vector2): Roughness in x and y directions, range [0.0, 1.0]. Defaults to (0.0, 0.0). + + + +* **`glossiness_anisotropy`**: Calculates anisotropic surface roughness from a scalar glossiness and anisotropy parameterization. This node gives the same result as roughness anisotropy except that the glossiness value is an inverted roughness value. To be used as a convenience for shading models using the glossiness parameterization. Output type "vector2". + * `glossiness` (float): Roughness value, range [0.0, 1.0]. Defaults to 0.0. + * `anisotropy` (float): Amount of anisotropy, range [0.0, 1.0]. Defaults to 0.0. + + + +* **`blackbody`**: Returns the radiant emittance of a blackbody radiator with the given temperature. Output type "color3". + * `temperature` (float): Temperature in Kelvin. Default is 5000. + + + +* **`artistic_ior`**: Converts the artistic parameterization reflectivity and edge_color to complex IOR values. To be used with the [<conductor_bsdf> node](#node-conductor-bsdf). + * `reflectivity` (color3): Reflectivity per color component at facing angles. Default is (0.947, 0.776, 0.371). + * `edge_color` (color3): Reflectivity per color component at grazing angles. Default is (1.0, 0.982, 0.753). + * `ior` (**output**, vector3): Computed index of refraction. + * `extinction` (**output**, vector3): Computed extinction coefficient. + + + +# Shading Model Examples + +This section contains examples of shading model implementations using the MaterialX PBS library. For all examples, the shading model is defined via a <nodedef> interface plus a nodegraph implementation. The resulting nodes can be used as shaders by a MaterialX material definition. + + +## Autodesk Standard Surface + +This is a surface shading model used in Autodesk products created by the Solid Angle team for the Arnold renderer. It is an über shader built from ten different BSDF layers[^13]. + +A MaterialX definition and nodegraph implementation of Autodesk Standard Surface can be found here: +[https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/standard_surface.mtlx](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/standard_surface.mtlx) + + +## UsdPreviewSurface + +This is a shading model proposed by Pixar for USD[^14]. It is meant to model a physically based surface that strikes a balance between expressiveness and reliable interchange between current day DCC’s and game engines and other real-time rendering clients. + +A MaterialX definition and nodegraph implementation of UsdPreviewSurface can be found here: +[https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/usd_preview_surface.mtlx](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/usd_preview_surface.mtlx) + + +## Khronos glTF PBR + +This is a shading model using the PBR material extensions in Khronos glTF specification. + +A MaterialX definition and nodegraph implementation of glTF PBR can be found here: +[https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/gltf_pbr.mtlx](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/bxdf/gltf_pbr.mtlx) + + +# Shading Translation Graphs + +The MaterialX PBS Library includes a number of nodegraphs that can be used to approximately translate the input parameters for one shading model into values to drive the inputs of a different shading model, to produce the same visual results to the degree the differences between the shading models allow. Currently, the library includes translation graphs for: + +* Autodesk Standard Surface to UsdPreviewSurface +* Autodesk Standard Surface to glTF + + +# References + +[^1]: + +[^2]: M. Oren, S.K. Nayar, **Diffuse reflectance from rough surfaces**, , 1993 + +[^3]: Brent Burley, **Physically-Based Shading at Disney**, , 2012 + +[^4]: Bruce Walter et al., **Microfacet Models for Refraction through Rough Surfaces**, , 2007 + +[^5]: Brent Burley, **Physically-Based Shading at Disney**, , 2012 + +[^6]: Ole Gulbrandsen, **Artist Friendly Metallic Fresnel**, , 2014 + +[^7]: Sony Pictures Imageworks, **Revisiting Physically Based Shading at Imageworks**, + +[^8]: Pixar, **Approximate Reflectance Profiles for Efficient Subsurface Scattering**, 2015 + +[^9]: Sony Pictures Imageworks, **Production Friendly Microfacet Sheen BRDF**, + +[^10]: Laurent Belcour, Pascal Barla, **A Practical Extension to Microfacet Theory for the Modeling of Varying Iridescence**, , 2017 + +[^11]: **Standard File Format for Electronic Transfer of Photometric Data**, + +[^12]: Matt Pharr, Wenzel Jakob, Greg Humphreys, **Physically Based Rendering: From Theory To Implementation**, Chapter 11.2, + +[^13]: 13. Autodesk, **A Surface Standard**, , 2019. + +[^14]: 14. Pixar, **UsdPreviewSurface Proposal**, <, 2018. + diff --git a/documents/Specification/inprog_v1.39/MaterialX.Specification.md b/documents/Specification/inprog_v1.39/MaterialX.Specification.md new file mode 100644 index 0000000000..c0dc5c9b48 --- /dev/null +++ b/documents/Specification/inprog_v1.39/MaterialX.Specification.md @@ -0,0 +1,2534 @@ + + + +# MaterialX: An Open Standard for Network-Based CG Object Looks + +**Version 1.39** +Doug Smythe - Industrial Light & Magic +Jonathan Stone - Lucasfilm Advanced Development Group +April 20, 2023 + + +# Introduction + +Computer graphics production studios commonly use workflows involving multiple software tools for different parts of the production pipeline. There is also a significant amount of sharing and outsourcing of work across facilities, requiring companies to hand off fully look-developed models to other divisions or studios which may use different software packages and rendering systems. In addition, studio rendering pipelines that previously used monolithic shaders built by expert programmers or technical directors with fixed, predetermined texture-to-shader connections and hard-coded texture color-correction options are now using more flexible node-based shader networks built up by connecting images and procedurals to shader inputs through a graph of image processing and blending operators. + +At least four distinct interrelated data relationships are required to specify the complete "look" of a CG object: + +1. _Image processing networks_ of sources, operators, connections and input values, outputting a number of spatially-varying data streams. +2. _Geometry-specific information_ such as associated texture filenames or IDs for various map types. +3. Associations between spatially-varying data streams and/or uniform values and the inputs of surface, volume, or other shaders, defining a number of _materials_. +4. Associations between materials and specific geometries to create a number of _looks_. + +**MaterialX** addresses the need for an open, platform-independent, well-defined standard for specifying the "look" of computer graphics objects built using node networks by defining a material content schema along with a corresponding XML-based file format to read and write MaterialX content. The MaterialX schema defines a number of primary element types plus several supplemental and sub-element types, as well as a set of **standard nodes** with specific functionality for defining data-processing graphs, shaders and materials. + +This document describes the core MaterialX specification. Companion documents [**MaterialX Physically Based Shading Nodes**](./MaterialX.PBRSpec.md), [**MaterialX Geometry Extensions**](./MaterialX.GeomExts.md) and [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md) describe additional node and element types and other information about the library. + + + +## Table of Contents + +**[Introduction](#introduction)** + +**[MaterialX Overview](#materialx-overview)** + [Definitions](#definitions) + [MaterialX Names](#materialx-names) + [MaterialX Data Types](#materialx-data-types) + [Custom Data Types](#custom-data-types) + [MTLX File Format Definition](#mtlx-file-format-definition) + [Color Spaces and Color Management Systems](#color-spaces-and-color-management-systems) + [Units](#units) + [MaterialX Namespaces](#materialx-namespaces) + [Geometric Properties](#geometric-properties) + [File Prefixes](#file-prefixes) + [Filename Substitutions](#filename-substitutions) + +**[Nodes](#nodes)** + [Inputs](#inputs) + [Node Graph Elements](#node-graph-elements) + [Output Elements](#output-elements) + + [Standard Source Nodes](#standard-source-nodes) +  [Texture Nodes](#texture-nodes) +  [Procedural Nodes](#procedural-nodes) +  [Geometric Nodes](#geometric-nodes) +  [Global Nodes](#global-nodes) +  [Application Nodes](#application-nodes) + + [Standard Operator Nodes](#standard-operator-nodes) +  [Math Nodes](#math-nodes) +  [Adjustment Nodes](#adjustment-nodes) +  [Compositing Nodes](#compositing-nodes) +  [Conditional Nodes](#conditional-nodes) +  [Channel Nodes](#channel-nodes) +  [Convolution Nodes](#convolution-nodes) +  [Shader Nodes](#shader-nodes) + + [Standard Node Inputs](#standard-node-inputs) + [Standard UI Attributes](#standard-ui-attributes) + [Backdrop Elements](#backdrop-elements) + [Node Graph Examples](#node-graph-examples) + +**[Customization, Targeting and Shading](#customization-targeting-and-shading)** + [Target Definition](#target-definition) + [Custom Attributes and Inputs](#custom-attributes-and-inputs) + + [Custom Nodes](#custom-nodes) +  [Custom Node Declaration NodeDef Elements](#custom-node-declaration-nodedef-elements) +   [NodeDef Parameter Interface](#nodedef-parameter-interface) +   [NodeDef Input Elements](#nodedef-input-elements) +   [NodeDef Token Elements](#nodedef-token-elements) +   [NodeDef Output Elements](#nodedef-output-elements) +  [Custom Node Definition Using Implementation Elements](#custom-node-definition-using-implementation-elements) +   [Implementation AOV Elements](#implementation-aov-elements) +   [Example Custom Nodes Defined by External File Implementations](#example-custom-nodes-defined-by-external-file-implementations) +  [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) +   [Functional Nodegraphs](#functional-nodegraphs) +   [Compound Nodegraphs](#compound-nodegraphs) +   [Example Custom Node Defined by a Nodegraph](#example-custom-node-defined-by-a-nodegraph) +  [Custom Node Use](#custom-node-use) + [Shader Nodes](#shader-nodes) +  [Standard Shader-Semantic Operator Nodes](#standard-shader-semantic-operator-nodes) +  [AOV Output Elements](#aov-output-elements) +   [AOVOutput Example](#aovoutput-example) + [Material Nodes](#material-nodes) +  [Material Inheritance](#material-inheritance) +  [Example Pre-Shader Compositing Material](#example-pre-shader-compositing-material) + [Material Variants](#material-variants) + +**[References](#references)** + + +# MaterialX Overview + +The diagram below gives a high-level overview of a typical MaterialX look definition. A directed acyclic graph of pattern generation and processing nodes is connected to inputs of a surface Shader which defines a layered BSDF response. One or more shaders can be connected to form a Material, which is ultimately associated with specific scene geometry via a MaterialAssign, a number of which comprise a Look. The assignments of Materials to geometries can be defined within a MaterialX document in applications supporting MaterialX Geometry Extensions, or using an alternative mechanism such as USD[^1] or a native application's toolset. Each of the pattern nodes and even the Shaders may in turn be implemented using a graph of nodes: these NodeGraphs are given a parameter interface using NodeDefs, and these implementations may be reused with different input values just like any other Standard node defined by MaterialX. + +![MaterialX Overview Diagram](media/MaterialX_1.39_Overview_v5.png "MaterialX Overview Diagram") + +MaterialX also allows the specification of additional information not shown in this diagram, such as geometry-specific properties, material variations, arbitrary custom inputs and attributes for nodes, rendering-target-specific versions of shaders, nodes and implementations, external compiled or generated shader implementations, and much more. + + + +## Definitions + +Because the same word can be used to mean slightly different things in different contexts, and because each studio and package has its own vocabulary, it's important to define exactly what we mean by any particular term in this proposal and use each term consistently. + +An **Element** is a named object within a MaterialX document, which may possess any number of child elements and attributes. An **Attribute** is a named property of a MaterialX element. + +A **Node** is a function that generates or operates upon spatially-varying data. This specification provides a set of standard nodes with precise definitions, and also supports the creation of custom nodes for application-specific uses. The interface for a node’s incoming data is declared through **Inputs**, which may be spatially-varying or uniform, and **Tokens**, which are string values that can be substituted into filenames declared in node inputs. + +A **Pattern** is a node that generates or processes simple scalar, vector, and color data, and has access to local properties of any geometry that has been bound. + +A **Shader** is a node that can generate or process arbitrary lighting or BSDF data, and has access to global properties of the scene in which it is evaluated. + +A **Material** is a node which internally or externally references one or more shaders with specific data streams or uniform values bound to their inputs. + +A **Node Graph** is a directed acyclic graph of nodes, which may be used to define arbitrarily complex generation or processing networks. Common uses of Node Graphs are to describe a network of pattern nodes flowing into shader inputs, or to define a complex or layered node in terms of simpler nodes. + +A **Stream** refers to a flow of spatially-varying data from one node to another. A Stream most commonly consists of color, vector, or scalar data, but can transport data of any standard or custom type. + +A **Layer** is a named 1-, 2-, 3- or 4-channel color "plane" within an image file. Image file formats that do not support multiple or named layers within a file should be treated as if the (single) layer was named "rgba". + +A **Channel** is a single float value within a color or vector value, e.g. each layer of an image might have a red Channel, a green Channel, a blue Channel and an alpha Channel. + +A **Geometry** is any renderable object, while a **Partition** refers to a specific named renderable subset of a piece of geometry, such as a face set. + +A **Collection** is a recipe for building a list of geometries, which can be used as a shorthand for assigning e.g. a Material to a number of geometries in a Look. + +A **Target** is a software environment that interprets MaterialX content to generate images, with common examples being digital content creation tools and 3D renderers. + + + +## MaterialX Names + +All elements in MaterialX (nodes, materials, shaders, etc.) are required to have a `name` attribute of type "string". The `name` attribute of a MaterialX element is its unique identifier, and no two elements within the same scope (i.e. elements with the same parent) may share a name. + +Element names are restricted to upper- and lower-case letters, numbers, and underscores (“_”) from the ASCII character set; all other characters and symbols are disallowed. MaterialX names are case-sensitive and are not allowed to begin with a digit. + + + +## MaterialX Data Types + +All values, input and output ports, and streams in MaterialX are strongly typed, and are explicitly associated with a specific data type. The following standard data types are defined by MaterialX: + +**Base Types**: + +``` + integer, boolean, float, + color3, color4, + vector2, vector3, vector4, + matrix33, matrix44, string, filename +``` + +**Array Types**: + +``` + integerarray, floatarray, + color3array, color4array, + vector2array, vector3array, vector4array, + stringarray +``` + + +The following examples show the appropriate syntax for MaterialX attributes in MTLX files: + +**Integer**, **Float**: just a value inside quotes: + +``` + integervalue = "1" + floatvalue = "1.0" +``` + +**Boolean**: the lower-case word "true" or "false" inside quotes: + +``` + booleanvalue = "true" +``` + +**Color** types: MaterialX supports two different color types: + +* color3 (red, green, blue) +* color4 (red, green, blue, alpha) + +Color channel values should be separated by commas (with or without whitespace), within quotes: + +``` + color3value = "0.1,0.2,0.3" + color4value = "0.1,0.2,0.3,1.0" +``` + +Note: all color3 values and the RGB components of a color4 value are presumed to be specified in the "working color space" defined in the enclosing <materialx> element, although any element within a document may provide a `colorspace` attribute that explicitly states the space in which color values within its scope should be interpreted; implementations are expected to translate those color values into the working color space before performing computations with those values. See the [Color Spaces and Color Management Systems](#color-spaces-and-color-management-systems) section below. + +**Vector** types: similar to colors, MaterialX supports three different vector types: + +* vector2 (x, y) +* vector3 (x, y, z) +* vector4 (x, y, z, w) + +Coordinate values should be separated by commas (with or without whitespace), within quotes: + +``` + vector2value = "0.234,0.885" + vector3value = "-0.13,12.883,91.7" + vector4value = "-0.13,12.883,91.7,1.0" +``` + +While colorN and vectorN types both describe vectors of floating-point values, they differ in a number of significant ways. First, the final channel of a color4 value is interpreted as an alpha channel by compositing operators, and is only meaningful within the [0, 1] range, while the fourth channel of a vector4 value _could be_ (but is not necessarily) interpreted as the "w" value of a homogeneous 3D vector. Additionally, values of type color3 and color4 are always associated with a particular color space and are affected by color transformations, while values of type vector3 and vector4 are not. More detailed rules for colorN and vectorN operations may be found in the [Standard Operator Nodes](#standard-operator-nodes) section of the specification. + +**Matrix** types: MaterialX supports two matrix types that may be used to represent geometric and color transforms. The `matrix33` and `matrix44` types, respectively, represent 3x3 and 4x4 matrices and are written as nine or sixteen float values separated by commas, in row-major order: + +``` + matrix33value = "1,0,0, 0,1,0, 0,0,1" + matrix44value = "1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1" +``` + +**String**: literal text within quotes. See the [MTLX File Format Definition](#mtlx-file-format-definition) section for details on representing special characters within string data. + +``` + stringvalue = "some text" +``` + +**Filename**: attributes of type "filename" are just strings within quotes, but specifically mean a Uniform Resource Identifier ([https://en.wikipedia.org/wiki/Uniform_Resource_Identifier](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)) optionally containing one or more Filename Substitution strings (see below) that represents a reference to an external asset, such as a file on disk or a query into a content management system. + +``` + filevalue = "diffuse/color01.tif" + filevalue = "/s/myshow/assets/myasset/v102.1/wetdrips/drips.{frame}.tif" + filevalue = "https://github.com/organization/project/tree/master/src/node.osl" + filevalue = "cmsscheme:myassetdiffuse..tif?ver=current" +``` + +**IntegerArray**, **FloatArray**, **Color3Array**, **Color4Array**, **Vector2Array**, **Vector3Array**, **Vector4Array**, **StringArray**: any number of values (including zero) of the same base type, separated by commas (with or without whitespace), within quotes; arrays of color3’s, color4’s, vector2's, vector3's or vector4's are simply a 1D list of channel values in order, e.g. "r0, g0, b0, r1, g1, b1, r2, g2, b2". Individual string values within stringarrays may not contain commas or semicolons, and any leading and trailing whitespace characters in them is ignored. MaterialX does not support multi-dimensional or nested arrays. Array-typed inputs to nodes must be static uniform values of a length specified by another uniform input value of the node, or implicitly by the node's implementation requirements. Nodes cannot output an Array type. + +``` + integerarrayvalue = "1,2,3,4,5" + floatarrayvalue = "1.0, 2.2, 3.3, 4.4, 5.5" + color3arrayvalue = ".1,.2,.3, .2,.3,.4, .3,.4,.5" + color4arrayvalue = ".1,.2,.3,1, .2,.3,.4,.98, .3,.4,.5,.9" + vector2arrayvalue = "0,.1, .4,.5, .9,1.0" + vector3arrayvalue = "-0.2,0.11,0.74, 5.1,-0.31,4.62" + vector4arrayvalue = "-0.2,0.11,0.74,1, 5.1,-0.31,4.62,1" + stringarrayvalue = "hello, there, world" +``` + + + +## Custom Data Types + +In addition to the standard data types, MaterialX supports the specification of custom data types for the inputs and outputs of shaders and custom nodes. This allows documents to describe data streams of any complex type an application may require; examples might include spectral color samples or compound geometric data. + +Types can be declared to have a specific semantic, which can be used to determine how values of that type should be interpreted, and how nodes outputting that type can be connected. Currently, MaterialX defines three semantics: + +* "`color`": the type is interpreted to represent or contain a color, and thus should be color-managed as described in the [Color Spaces and Color Management Systems](#color-spaces-and-color-management-systems) section. +* "`shader`": the type is interpreted as a shader output type; nodes or nodegraphs which output a type with a "shader" semantic can be used to define a shader-type node, which can be connected to inputs of "material"-type nodes. +* "`material`": the type is interpreted as a material output type; nodes or nodegraphs which output a type with a "material" semantic can be referenced by a <materialassign> in a <look>. + +Types not defined with a specific semantic are assumed to have semantic="default". + +Custom types are defined using the <typedef> element: + +``` + + +``` + +Attributes for <typedef> elements: + +* `name` (string, required): the name of this type. Cannot be the same as a built-in MaterialX type. +* `semantic` (string, optional): the semantic for this type (see above); the default semantic is "default". +* `context` (string, optional): a semantic-specific context in which this type should be applied. For "shader" semantic types, `context` defines the rendering context in which the shader output is interpreted; please see the [Shader Nodes](#shader-nodes) section for details. +* `inherit` (string, optional): the name of another type that this type inherits from, which can be either a built-in type or a custom type. Applications that do not have a definition for this type can use the inherited type as a "fallback" type. +* `hint` (string, optional): A hint to help those creating code generators understand how the type might be defined. The following hints for typedefs are currently defined: + * "halfprecision": the values within this type are half-precision + * "doubleprecision: the values within this type are double-precision + +Once a custom type is defined by a <typedef>, it can then be used in any MaterialX element that allows "any MaterialX type"; the list of MaterialX types is effectively expanded to include the new custom type. It should be noted however that the <typedef> is only declaring the existence of the type and perhaps some hints about its intended definition, but it is up to each application and code generator to provide its own precise definition for any type. + +The standard MaterialX distribution includes definitions for four "shader"-semantic data types: **surfaceshader**, **displacementshader**, **volumeshader**, and **lightshader**. These types are discussed in more detail in the [Shader Nodes](#shader-nodes) section below. + + + +## MTLX File Format Definition + +An MTLX file (with file extension ".mtlx") has the following general form: + +``` + + + + +``` + +That is, a standard XML declaration line followed by a root <materialx> element, which contains any number of MaterialX elements and sub-elements. The default character encoding for MTLX files is UTF-8, and this encoding is expected for the in-memory representation of string values in MaterialX implementations. + +Standard XML XIncludes are supported ([http://en/wikipedia.org/wiki/XInclude](http://en/wikipedia.org/wiki/Xinclude)), as well as standard XML comments and the XML character entities `"`, `&`, `'`, `<` and `>`: + +``` + + + +``` + +To support stringarray types, MaterialX supports a non-standard XML convention where a comma (and any following whitespace) is a separator for strings within a stringarray, a comma or semicolon preceded by a backslash is interpreted as a regular comma or semicolon rather than as a separator, and two backslashes are interpreted as a single backslash. + +Each XIncluded document must itself be a valid MTLX file, containing an XML header and its own root `` element, the children of which are added to the root element of the including document. Hierarchical root-level attributes such as `colorspace` and `namespace` are distributed to the included children to maintain correct semantics within the including MaterialX document. + +Attributes for a <materialx> element: + +* `version` (string, required): a string containing the version number of the MaterialX specification that this document conforms to, specified as a major and minor number separated by a dot. The MaterialX library automatically upgrades older-versioned documents to the current MaterialX version at load time. +* `colorspace` (string, optional): the name of the "working color space" for this element and all of its descendants. This is the default color space for all image inputs and color values, and the color space in which all color computations will be performed. The default is "none", for no color management. +* `namespace` (string, optional): defines the namespace for all elements defined within this <materialx> scope. Please see the [MaterialX Namespaces](#materialx-namespaces) section below for details. + + + +## Color Spaces and Color Management Systems + +MaterialX supports the use of color management systems to associate RGB colors and images with specific color spaces. MaterialX documents typically specify the working color space of the application that created them, and any input color or image described in the document can specify the name of its color space if different from the working color space. This allows applications using MaterialX to transform color values within input colors and images from their original color space into a desired working color space upon ingest. MaterialX does not specify _how_ or _when_ color values should be transformed: that is up to the host application, which can use any appropriate method including code generation, conversion when loading images into memory, maintaining cached or pre-converted image textures, etc. It is generally presumed that the working color space of a MaterialX document will be linear (as opposed to log, a display-referred space such as sRGB, or some other non-linear encoding), although this is not a firm requirement. + +By default, MaterialX supports the following color spaces as defined in ACES 1.2 ([http://www.oscars.org/science-technology/sci-tech-projects/aces)](http://www.oscars.org/science-technology/sci-tech-projects/aces), and applications rendering MaterialX documents are expected to transform input colors and images from these spaces to the color space of their renderer. One straightforward option for providing this support is to leverage MaterialX code generators, which support these transforms automatically, but applications may use any appropriate means to handle the transforms on their own. + +* `srgb_texture` +* `lin_rec709` +* `g22_rec709` +* `g18_rec709` +* `acescg` +* `lin_ap1 (alias for "acescg")` +* `g22_ap1` +* `g18_ap1` +* `lin_srgb` +* `adobergb` +* `lin_adobergb` + +The working color space of a MaterialX document is defined by the `colorspace` attribute of its root <materialx> element, and it is strongly recommended that all <materialx> elements define a specific `colorspace` if they wish to use a color-managed workflow rather than relying on a default colorspace setting from an external configuration file. + +The color space of individual color image files and values may be defined via a `colorspace` attribute in an input which defines a filename or value. Color images and values in spaces other than the working color space are expected to be transformed by the application into the working space before computations are performed. In the example below, an image file has been defined in the “srgb_texture” color space, while its default value has been defined in “lin_rec709”; both should be transformed to the application’s working color space before being applied to any computations. + +``` + + + + +``` + +MaterialX reserves the color space name "none" to mean no color space conversion should be applied to the images and color values within their scope. + + + +## Units + +MaterialX allows floating-point and vector values to be defined in terms of a specific unit and unit type, and can automatically convert values from their specified unit into a scene unit of the same type specified by the application. This allows images and the quantities they represent such as displacement amount to be specified at an absolute real-world size, and then be converted automatically to the expected scene units of the application. + +Unit types are defined using a <unittypedef> element, and a set of units of that type is defined using a <unitdef> element with one or more child <unit> elements: + +``` + + + + + + + + + + + + +``` + +The <unittypedef> defines the name of a unittype, while the <unitdef> defines any number of units for a unittype along with the multiplicative conversion `scale` values relative to the other units. Additional unit definitions for any unit type may be done by providing another <unitdef> with the same `unittype` attribute value. + +Any input or other floating-point value may specify a `unit` and/or `unittype` attribute subject to guidelines clarified throughout this document. Units and unittypes may also be provided for floatarray, vectorN and vectorNarray quantities, with all components of the vector or all values in the array using the same unit, and for "filename"-type input, in which case the `unit` and/or `unittype` attribute applies to the float or vectorN values read from those files. It is not expected that all inputs will have defined units or unittypes; in fact, it is expected that the vast majority of inputs will have neither. Units and unittypes should only be specified where specific units are important and it is reasonably expected that unit conversion may need to take place. + +Please refer to the [Inputs](#inputs), [Custom Node Declaration NodeDef Elements](#custom-node-declaration-nodedef-elements), [Geometric Properties](#geometric-properties) and [Geometric Nodes](#geometric-nodes) sections below and in the MaterialX Geometry Extensions document for additional specific requirements for the use of units. + + + +## MaterialX Namespaces + +MaterialX supports the specification of “namespaces”, which qualify the MaterialX names of all elements within their scope. Namespaces are specified via a `namespace` attribute in a <materialx> element, and other MaterialX files which <xi:include> this .mtlx file can refer to its content without worrying about element or object naming conflicts, similar to the way namespaces are used in various programming languages. It is permissible for multiple <materialx> elements to specify the same namespace; the elements from each will simply be merged into the same namespace. <materialx> elements which do not specify a namespace will define elements into the (unnamed) global namespace. MaterialX namespaces are most commonly used to define families of custom nodes (nodedefs), material libraries, or commonly-used network shaders or nodegraphs. + +References to elements in a different namespace are qualified using the syntax "_namespace_:_elementname_", where _namespace_ is the namespace at the scope of the referenced element and _elementname_ is the name of the referenced element. References to elements in the same namespace, or to elements in the global namespace, should not be qualified. + +#### Namespace Examples + +Mtllib.mtlx contains the following (assuming that "..." contains any necessary material input connections and other element definitions): + +``` + + + ... + + ... + + + ... + + +``` + +Then another MaterialX file could reference these materials like this: + +``` + + ... + + + + +``` + +Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom color3-typed node "mynoise" with a single float input "f", it could be used in a node graph like this: + +``` + + + +``` + +A `namespace` attribute may also be added to individual <nodedef>s or <nodegraph>s, in which case the `name` and `node` of a <nodedef>, or just the `name` of a <nodegraph> will be assigned to the specified `namespace`. In a <nodegraph>, the `nodedef` must include a namespace reference if the <nodedef> to which it refers is defined in a specific namespace, even if it's the same namespace as the <nodegraph>: this is because the `namespace` only applies to the content that is created by or contained within an element, not to anything external referenced by that element. + +``` + + + + + + + + + + +``` + + + +## Geometric Properties + +Geometric Properties, or "geomprops", are intrinsic or user-defined surface coordinate properties of geometries referenced in a specific space and/or index, and are functionally equivalent to USD's concept of "primvars". A number of geometric properties are predefined in MaterialX: `position`, `normal`, `tangent`, `bitangent`, `texcoord` and `geomcolor`, the values of which can be accessed in nodegraphs using elements of those same names; see the [Geometric Nodes](#geometric-nodes) section below for details. The value of a varying geometric property can also be used as the default value for a node input using a `defaultgeomprop` attribute. + +One may also define custom geometric properties using a <geompropdef> element: + +``` + +``` + +e.g. + +``` + + +``` + +The `type` of the geomprop may be any non-array MaterialX type, although `string`- or `filename`-type geomprops must be declared with uniform="true". The "geomprop", "space" and "index" attributes are optional; if "geomprop" is specified, it must be one of the standard geometric properties noted above, and if it is not specified, the new geomprop is a blind geometric property, e.g. one that can be referenced but which MaterialX knows no details about. The "space" and "index" attributes may only be specified if a "geomprop" attribute is specified and the standard geomproperty supports it. "Geomprop", "space" and "index" attributes may not be specified for `uniform="true"` geomprops. + +Once defined, a custom geomprop name may be used any place that a standard geomprop can: + +``` + +``` + +A geompropdef may also specify a `unittype` and a `unit` to indicate that the geometric property is defined in terms of a specific unit. If a geomprop with a defined unit is accessed in a nodegraph using <geompropvalue>, the geometric property value will be converted from the unit specified by the geompropdef to the application-specified scene unit. + +``` + +``` + + + +## File Prefixes + +As a shorthand convenience, MaterialX allows the specification of a `fileprefix` attribute which will be prepended to input values of type "filename" (e.g. `file` inputs in `` nodes, or any shader input of type "filename") specified within the scope of the element defining the `fileprefix`. Note that `fileprefix` values are only prepended to input with a `type` attribute that explicitly states its data type as “filename”. Since the values of the prefix and the filename are string-concatenated, the value of a `fileprefix` should generally end with a "/". Fileprefixes are frequently used to split off common path components for asset directories, e.g. to define an asset's "texture root" directory. + +So the following snippets are equivalent: + +``` + + + + + + + + + + + + + + + + + +``` + +Note in the second example that `` "in2" redefined `fileprefix` for itself, and that any other nodes in the same nodegraph would use the fileprefix value ("textures/color/") defined in the parent/enclosing scope. + +Note: Application implementations have access to both the raw input values and attributes (e.g. the "file" name and the current "fileprefix") and to fully-resolved filenames at the scope of any given element. + + + +## Filename Substitutions + +Filename input values for various nodes can include one or more special strings, which will be replaced as described in the following table. Substitution strings within <>'s come from the current geometry, strings within []'s come from the MaterialX state, and strings within {}'s come from the host application environment. + +| Token | Description | +| ---- | ---- | +| <UDIM> | A special geometry token that will be replaced with the computed four digit Mari-style "udim" value at render or evaluation time based on the current point’s uv value, using the formula UDIM = 1001 + U + V*10, where U is the integer portion of the u coordinate, and V is the integer portion of the v coordinate. | +| <UVTILE> | A special geometry token that will be replaced with the computed Mudbox-style "uU_vV" string, where U is 1+ the integer portion of the u coordinate, and V is 1+ the integer portion of the v coordinate. | +| [interface token] | The value of a specified token declared in the containing nodegraph's <nodedef> interface; the value for the token may be set in the shader node in a material referencing the node or within a <variant>; it is an error if the same token is defined in more than one of those places for the current geometry. | +| {hostattr} | The host application may define other variables which can be resolved within filenames. | +| {frame} | A special string that will be replaced by the current frame number, as defined by the host environment. | +| {0Nframe} | A special string that will be replaced by the current frame number padded with zeros to be N digits total (replace N with a number): e.g. {04frame} will be replaced by a 4-digit zero-padded frame number such as "0010". | + + +Note: Implementations are expected to retain substitution strings within filenames upon export rather than "baking them out" into fully-evaluated filenames. Applications using USD for geometry and assignments may additionally use a <_geometry token_> (a.k.a. "<_primvarname_>") as the entire filename string to access an entire string primvar value unchanged (though that string value may contain the USD-supported <UDIM> token). + + + +# Nodes + +Nodes are individual data generation or processing "blocks". Node functionality can range from simple operations such as returning a constant color value or adding two input values, to more complex image processing operations, 3D spatial data operations, or even complete shader BxDFs. Nodes are connected together into a network or "node graph", and pass typed data streams between them. + +Individual node elements have the form: + +``` + + + ...additional input or token elements... + +``` + +where _nodecategory_ is the general "category" of the node (e.g. "image", "add" or "mix"), `name` (string, required) defines the name of this instance of the node, which must be unique within the scope it appears in, and `type` (string, required) specifies the MaterialX type (typically float, colorN, or vectorN) of the output of that node. If the application uses a different name for this instance of the node in the user interface, a `uiname` attribute may be added to the <_nodecategory_> element to indicate the name of the node as it appears to the user. + +Node elements may optionally specify a `version` string attribute in "_major_[._minor_]" format, requesting that a specific version of that node's definition be used instead of the default version. Normally, the types of a node's inputs and outputs are sufficient to disambiguate which signature of the applicable version of a node is intended, but if necessary, a node instantiation may also declare a specific nodedef name to precisely define exactly which node signature is desired. Please refer to the [Custom Node Declaration NodeDef Elements](#custom-node-declaration-nodedef-elements) section below for further details. + +MaterialX defines a number of Standard Nodes which all implementations should support as described to the degree their architecture and capabilities allow. One can define new nodes by declaring their parameter interfaces and providing portable or target-specific implementations. Please see the [Custom Nodes](#custom-nodes) section for notes and implementation details. + + + +## Inputs + +Node elements contain zero or more <input> elements defining the name, type, and value or connection for each node input. Input elements can assign an explicit uniform value by providing a `value` attribute, make a connection to the output of another node by providing a `nodename` attribute, or make a connection to the output of a nodegraph by providing a `nodegraph` attribute. An optional `output` attribute may also be provided for <input> elements, allowing the input to connect to a specific, named output of the referenced upstream node or nodegraph. If the referenced node/nodegraph has multiple outputs, `output` is required; if it has only one output, the `output` attribute of the <input> is ignored. Input elements may be defined to only accept uniform values, in which case the input may provide a `value` or a `nodename` connection to the output of a [<constant> node](#node-constant) (possibly through one or more no-op [<dot> nodes](#node-dot)) or any other node whose output is explicitly declared to be "uniform" (such as [<geompropvalueuniform>](#node-geompropvalueuniform)), but may not provide a `nodename` or `nodegraph` connection to any arbitrary node output or to any nodegraph output. String- and filename-type inputs are required to be "uniform", as are any array-typed inputs. Input elements may be connected to an external parameter interface in the node definition, allowing them to be assigned values from materials or node instantiations; this includes "uniform" and string/filename-type inputs, however, the same connectability restrictions listed above apply to the inputs of the material or node instance. Inputs may only be connected to node/nodegraph outputs or nodedef interface inputs of the same type, though it is permissible for a `string`-type output to be connected to a `filename`-type input (but not the other way around). + +A float/vectorN input of a node, or a "filename"-type input referring to an image file containing float or vectorN values, may specify a unit for its value by providing a `unit` attribute, and that unit must be one associated with the `unittype` for that input in the nodedef, if specified; please see the [Units](#units) section above for details on declaring units and unittypes. If the nodedef for a node (see the [Custom Nodes](#custom-nodes) section below) does not declare a `unittype` for an input, the node may do so; it is not permissible to provide a `unit` for a node input without a compatible `unittype` being defined on either the node or applicable nodedef. + +``` + + + +``` + +Unless specified otherwise, all inputs default to a value of 0 in all channels for integer, float, color and vector types, "" for string and filename types, "false" for boolean types, the identity matrix for matrix types, and for array types, an appropriate-length array consisting of the default value for the array's base type. + +A node input must generally be connected to outputs of the same type, but float inputs may also be connected to any single channel within a multi-channel data types by adding an integer "channel" attribute, indicating the channel number (0-3) to extract from the input: + +``` + + + + + + + + + + +``` + +The "channel" attribute is valid in any non-token element that allows a "nodename" attribute. + +Standard MaterialX nodes have exactly one output, while custom nodes may have any number of outputs; please see the [Custom Nodes](#custom-nodes) section for details. + + + +## Node Graph Elements + +A graph containing any number of nodes and output declarations forms a Node Graph, which may be enclosed within a <nodegraph> element to group them together into a single functional unit. Please see the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section below for details on how nodegraphs can be used to describe the functionality of new nodes. + +``` + + ...node element(s)... + ...output element(s)... + +``` + + + +## Output Elements + +Output data streams are defined using **<output>** elements, and may be used to declare which output streams are connectable to other MaterialX elements. Within a node graph, an <output> element declares an output stream that may be connected to a shader input or to the input of a referencing node in another graph when the nodegraph is the implementation of a custom node. See the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section for details on the use of node graphs as node implementations. + +``` + + +``` + +Attributes for Output elements: + +* `name` (string, required): the name of the output +* `type` (string, required): the MaterialX type of the output +* `nodename` (string, optional): the name of a node at the same scope within the document, whose result value will be output. This attribute is required for <output> elements within a node graph, but is not allowed in <output> elements within a <nodedef>. +* `output` (string, optional): if the node specified by `nodename` has multiple outputs, the name of the specific output to connect this <output> to. +* `uniform` (boolean, optional): If set to "true", then the output of this node is treated as a uniform value, and this output may be connected to a uniform input of the same (or compatible) type. It is up to the application creating the nodegraph to ensure that the value actually is uniform. Default is "false". +* `colorspace` (string, optional): the name of the color space for the output image. Applications that support color space management are expected to perform the required transformations of output colors into this space. +* `width` (integer, optional): the expected width in pixels of the output image. +* `height` (integer, optional): the expected height in pixels of the output image. +* `bitdepth` (integer, optional): the expected per-channel bit depth of the output image, which may be used to capture expected color quantization effects. Common values for `bitdepth` are 8, 16, 32, and 64. It is up to the application to determine what the internal representation of any declared bit depth is (e.g. scaling factor, signed or unsigned, etc.). + +The `colorspace`, `width`, `height` and `bitdepth` attributes are intended to be used in applications which process node graphs in 2D space and save or cache outputs as images for efficiency. + + + +## Standard Source Nodes + +Source nodes use external data and/or procedural functions to form an output; they do not have any required inputs. Each source node must define its output type. + +This section defines the Source Nodes that all MaterialX implementations are expected to support. Standard Source Nodes are grouped into the following classifications: [Texture Nodes](#texture-nodes), [Procedural Nodes](#procedural-nodes), [Geometric Nodes](#geometric-nodes), [Global Nodes](#global-nodes) and [Application Nodes](#application-nodes). + + +### Texture Nodes + +Texture nodes are used to read filtered image data from image or texture map files for processing within a node graph. + +``` + + + + + + + + +``` + +Standard Texture nodes: + + + +* **`image`**: samples data from a single image, or from a layer within a multi-layer image. When used in the context of rendering a geometry, the image is mapped onto the geometry based on geometry UV coordinates, with the lower-left corner of an image mapping to the (0,0) UV coordinate (or to the fractional (0,0) UV coordinate for tiled images). + * `file` (uniform filename): the URI of an image file. The filename can include one or more substitutions to change the file name (including frame number) that is accessed, as described in the [Filename Substitutions](#filename-substitutions) section above. + * `layer` (uniform string): the name of the layer to extract from a multi-layer input file. If no value for `layer` is provided and the input file has multiple layers, then the "default" layer will be used, or "rgba" if there is no "default" layer. Note: the number of channels defined by the `type` of the `` must match the number of channels in the named layer. + * `default` (float or colorN or vectorN): a default value to use if the `file` reference can not be resolved (e.g. if a <_geometry token_>, [_interface token_] or {_hostattr_} is included in the filename but no substitution value or default is defined, or if the resolved `file` URI cannot be read), or if the specified `layer` does not exist in the file. The `default` value must be the same type as the `` element itself. If `default` is not defined, the default color value will be 0.0 in all channels. + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the image data is read. Default is to use the current u,v coordinate. + * `uaddressmode` (uniform string): determines how U coordinates outside the 0-1 range are processed before sampling the image; see below. Default is "periodic". + * `vaddressmode` (uniform string): determines how V coordinates outside the 0-1 range are processed before sampling the image; see below. Default is "periodic". + * `filtertype` (uniform string): the type of texture filtering to use; standard values include "closest" (nearest-neighbor single-sample), "linear", and "cubic". If not specified, an application may use its own default texture filtering method. + + + + +The following values are supported by `uaddressmode` and `vaddressmode` inputs: + +* “constant”: Texture coordinates outside the 0-1 range return the value of the node's `default` input. +* “clamp”: Texture coordinates are clamped to the 0-1 range before sampling the image. +* “periodic”: Texture coordinates outside the 0-1 range "wrap around", effectively being processed by a modulo 1 operation before sampling the image. +* "mirror": Texture coordinates outside the 0-1 range will be mirrored back into the 0-1 range, e.g. u=-0.01 will return the u=0.01 texture coordinate value, and u=1.01 will return the u=0.99 texture coordinate value. + + +Texture nodes using `file*` inputs also support the following inputs to handle boundary conditions for image file frame ranges for all `file*` inputs: + +* `framerange` (uniform string): a string "_minframe_-_maxframe_", e.g. "10-99", to specify the range of frames that the image file is allowed to have, usually the range of image files on disk. Default is unbounded. +* `frameoffset` (integer): a number that is added to the current frame number to get the image file frame number. E.g. if `frameoffset` is 25, then processing frame 100 will result in reading frame 125 from the imagefile sequence. Default is no frame offset. +* `frameendaction` (uniform string): what to do when the resolved image frame number is outside the `framerange` range: + * "constant": Return the value of the node's `default` input (default action) + * "clamp": Hold the minframe image for all frames before _minframe_ and hold the maxframe image for all frames after _maxframe_ + * "periodic": Frame numbers "wrap around", so after the _maxframe_ it will start again at _minframe_ (and similar before _minframe_ wrapping back around to _maxframe_) + * "mirror": Frame numbers "mirror" or "ping-pong" at the endpoints of framerange, so a read of the frame after _maxframe_ will return the image from frame _maxframe_-1, and a read of the frame before _minframe_ will return the image from frame _minframe_+1. + +Arbitrary frame number expressions and speed changes are not supported. + +Additional texture nodes, including **``** and **``**, may be found in the [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md#supplemental-texture-nodes) document. + + + +### Procedural Nodes + +Procedural nodes are used to generate value data programmatically. + +``` + + + + + + + +``` + +Standard Procedural nodes: + + + +* **`constant`**: a constant value. + * `value` (any non-shader-semantic type): the value to output + + + +* **`tokenvalue`**: a constant "interface token" value, may only be connected to <token>s in nodes, not to <input>s. + * `value` (any uniform non-shader-semantic type): the token value to output; "enum" and "enumvalues" attributes may be provided to define a specific set of allowed token values. + + + +* **`ramplr`**: a left-to-right linear value ramp. + * `valuel` (float or colorN or vectorN): the value at the left (U=0) edge + * `valuer` (float or colorN or vectorN): the value at the right (U=1) edge + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the ramp interpolation is evaluated. Default is to use the first set of texture coordinates. + + + +* **`ramptb`**: a top-to-bottom linear value ramp. + * `valuet` (float or colorN or vectorN): the value at the top (V=1) edge + * `valueb` (float or colorN or vectorN): the value at the bottom (V=0) edge + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the ramp interpolation is evaluated. Default is to use the first set of texture coordinates. + + + +* **`splitlr`**: a left-right split matte, split at a specified U value. + * `valuel` (float or colorN or vectorN): the value at the left (U=0) edge + * `valuer` (float or colorN or vectorN): the value at the right (U=1) edge + * `center` (float): a value representing the U-coordinate of the split; all pixels to the left of "center" will be `valuel`, all pixels to the right of "center" will be `valuer`. Default is 0.5. + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the split position is evaluated. Default is to use the first set of texture coordinates. + + + +* **`splittb`**: a top-bottom split matte, split at a specified V value. + * `valuet` (float or colorN or vectorN): the value at the top (V=1) edge + * `valueb` (float or colorN or vectorN): the value at the bottom (V=0) edge + * `center` (float): a value representing the V-coordinate of the split; all pixels above "center" will be `valuet`, all pixels below "center" will be `valueb`. Default is 0.5. + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the split position is evaluated. Default is to use the first set of texture coordinates. + + + +* **`noise2d`**: 2D Perlin noise in 1, 2, 3 or 4 channels. + * `amplitude` (float or vectorN): the center-to-peak amplitude of the noise (peak-to-peak amplitude is 2x this value). Default is 1.0. + * `pivot` (float): the center value of the output noise; effectively, this value is added to the result after the Perlin noise is multiplied by `amplitude`. Default is 0.0. + * `period` (float or vectorN): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `texcoord` (vector2): the 2D texture coordinate at which the noise is evaluated. Default is to use the first set of texture coordinates. + + + +* **`noise3d`**: 3D Perlin noise in 1, 2, 3 or 4 channels. + * `amplitude` (float or vectorN): the center-to-peak amplitude of the noise (peak-to-peak amplitude is 2x this value). Default is 1.0. + * `pivot` (float): the center value of the output noise; effectively, this value is added to the result after the Perlin noise is multiplied by `amplitude`. Default is 0.0. + * `period` (float or vectorN): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate. + + + +* **`fractal2d`**: Zero-centered 2D Fractal noise in 1, 2, 3 or 4 channels, created by summing several octaves of 2D Perlin noise, increasing the frequency and decreasing the amplitude at each octave. + * `amplitude` (float or vectorN): the center-to-peak amplitude of the noise (peak-to-peak amplitude is 2x this value). Default is 1.0. + * `octaves` (integer): the number of octaves of noise to be summed. Default is 3. + * `lacunarity` (float or vectorN): the exponential scale between successive octaves of noise; must be an integer value if period is non-zero so the result is properly tileable. VectorN-output types can provide either a float (isotropic) or vectorN (anisotropic) values for lacunarity and diminish. Default is 2.0. + * `diminish` (float or vectorN): the rate at which noise amplitude is diminished for each octave. Should be between 0.0 and 1.0; default is 0.5. VectorN-output types can provide either a float (isotropic) or vectorN (anisotropic) values for lacunarity and diminish. + * `period` (float or vectorN): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `texcoord` (vector2): the 2D texture coordinate at which the noise is evaluated. Default is to use the first set of texture coordinates. + + + +* **`fractal3d`**: Zero-centered 3D Fractal noise in 1, 2, 3 or 4 channels, created by summing several octaves of 3D Perlin noise, increasing the frequency and decreasing the amplitude at each octave. + * `amplitude` (float or vectorN): the center-to-peak amplitude of the noise (peak-to-peak amplitude is 2x this value). Default is 1.0. + * `octaves` (integer): the number of octaves of noise to be summed. Default is 3. + * `lacunarity` (float or vectorN): the exponential scale between successive octaves of noise; must be an integer value if period is non-zero so the result is properly tileable. Default is 2.0. VectorN-output types can provide either a float (isotropic) or vectorN (anisotropic) values for `lacunarity` and `diminish`. + * `diminish` (float or vectorN): the rate at which noise amplitude is diminished for each octave. Should be between 0.0 and 1.0; default is 0.5. VectorN-output types can provide either a float (isotropic) or vectorN (anisotropic) values for `lacunarity` and `diminish`. + * `period` (float or vectorN): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate. + + + +* **`cellnoise1d`**: 1D cellular noise, 1 or 3 channels (type float or vector3). + * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for input coordinate repeated at that step. Default is 0, meaning the noise is not periodic. + * `in` (float): the 1D coordinate at which the noise is evaluated. + + + +* **`cellnoise2d`**: 2D cellular noise, 1 or 3 channels (type float or vector3). + * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `texcoord` (vector2): the 2D position at which the noise is evaluated. Default is to use the first set of texture coordinates. + + + +* **`cellnoise3d`**: 3D cellular noise, 1 or 3 channels (type float or vector3). + * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate. + + + +* **`worleynoise2d`**: 2D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features). + * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance". + * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for texture coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0. + * `texcoord` (vector2): the 2D position at which the noise is evaluated. Default is to use the first set of texture coordinates. + + + +* **`worleynoise3d`**: 3D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features). + * `metric` (uniform string): the distance metric to return, one of "distance" (Euclidean distance to feature), "distance2" (Euclidean distance squared), "manhattan" or "chebyshev". Default is "distance". + * `period` (float or vector3): the positive integer distance at which the noise function returns the same value for position coordinates repeated at that step. Default is 0, meaning the noise is not periodic. + * `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0. + * `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate. + + +To scale or offset the noise pattern generated by `noise3d`, `fractal3d` or `cellnoise3d`, use a <position> or other [Geometric Node](#geometric-nodes) (see below) connected to vector3 <multiply> and/or <add> nodes, in turn connected to the noise node's `position` input. To scale or offset `rampX`, `splitX`, `noise2d` or `cellnoise2d` input coordinates, use a <texcoord> or similar Geometric node processed by vector2 <multiply>, <rotate> and/or <add> nodes, and connect to the node's `texcoord` input. + +Additional procedural nodes, including **``**, may be found in the [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md#supplemental-procedural-nodes) document. + + + +### Geometric Nodes + +Geometric nodes are used to reference local geometric properties from within a node graph: + +``` + + + + +``` + +Standard Geometric nodes: + + + +* **`position`**: the coordinates associated with the currently-processed data, as defined in a specific coordinate space. This node must be of type vector3. + * `space` (uniform string): the name of the coordinate space in which the position is defined. Default is "object", see below for details. + + + +* **`normal`**: the geometric normal associated with the currently-processed data, as defined in a specific coordinate space. This node must be of type vector3. + * `space` (uniform string): the name of the coordinate space in which the normal vector is defined. Default is "object", see below for details. + + + +* **`tangent`**: the geometric tangent vector associated with the currently-processed data, as defined in a specific coordinate space. This node must be of type vector3. + * `space` (uniform string): the name of the coordinate space in which the tangent vector is defined. Default is "object", see below for details. + * `index` (uniform integer): the index of the texture coordinates against which the tangent is computed. The default index is 0. + + + +* **`bitangent`**: the geometric bitangent vector associated with the currently-processed data, as defined in a specific coordinate space. This node must be of type vector3. + * `space` (uniform string): the name of the coordinate space in which the bitangent vector is defined. Default is "object", see below for details. + * `index` (uniform integer): the index of the texture coordinates against which the tangent is computed. The default index is 0. + + + +* **`bump`**: offset the surface normal by a scalar value. This node must be of type type vector3, and is generally connected to a shader node's "normal" input. + * `height` (float): Amount to offset the surface normal. + * `scale` (float): Scalar to adjust the height amount. + * `normal` (vector3): Surface normal; defaults to the current world-space normal. + * `tangent` (vector3): Surface tangent vector, defaults to the current world-space tangent vector. + + + +* **`texcoord`**: the 2D or 3D texture coordinates associated with the currently-processed data. This node must be of type vector2 or vector3. + * `index` (uniform integer): the index of the texture coordinates to be referenced. The default index is 0. + + + +* **`geomcolor`**: the color associated with the current geometry at the current `position`, generally bound via per-vertex color values. Can be of type float, color3 or color4, and must match the type of the "color" bound to the geometry. + * `index` (uniform integer): the index of the color to be referenced, default is 0. + + + +* **`geompropvalue`**: the value of the specified varying geometric property (defined using <geompropdef>) of the currently-bound geometry. This node's type must match that of the referenced geomprop. + * `geomprop` (uniform string): the geometric property to be referenced. + * `default` (same type as the geomprop's value): a value to return if the specified `geomprop` is not defined on the current geometry. + + + +* **`geompropvalueuniform`**: the value of the specified uniform geometric property (defined using <geompropdef>) of the currently-bound geometry. This node's type must match that of the referenced geomprop. + * `geomprop` (uniform string): the geometric property to be referenced. + * `default` (same type as the geomprop's value): a value to return if the specified `geomprop` is not defined on the current geometry. + + + + +The following values are supported by the `space` inputs of Geometric nodes and when transforming from one space to another: + + +* "model": The local coordinate space of the geometry, before any local deformations or global transforms have been applied. +* "object": The local coordinate space of the geometry, after local deformations have been applied, but before any global transforms. +* "world": The global coordinate space of the geometry, after local deformations and global transforms have been applied. +* "tangent": A coordinate space defined by the tangent, bitangent and normal vectors of the geometry. + +Applications may also reference other renderer-specific named spaces, at the expense of portability. + + + +### Global Nodes + +Global nodes generate color data using non-local geometric context, requiring access to geometric features beyond the surface point being processed. This non-local context can be provided by tracing rays into the scene, rasterizing scene geometry, or any other appropriate method. + +``` + + + +``` + +Standard Global nodes: + + + +* **`ambientocclusion`**: Compute the ambient occlusion at the current surface point, returning a scalar value between 0 and 1. Ambient occlusion represents the accessibility of each surface point to ambient lighting, with larger values representing greater accessibility to light. This node must be of type float. + * `coneangle` (float): the half-angle of a cone about the surface normal, within which geometric surface features are considered as potential occluders. The unit for this input is degrees, and its default value is 90.0 (full hemisphere). + * `maxdistance` (float): the maximum distance from the surface point at which geometric surface features are considered as potential occluders. Defaults to 1e38, e.g. "unlimited". + + + +### Application Nodes + +Application nodes are used to reference application-defined properties within a node graph, and have no inputs: + +``` + + +``` + +Standard Application nodes: + + + +* **`frame`**: the current frame number as defined by the host environment. This node must be of type float. Applications may use whatever method is appropriate to communicate the current frame number to the <frame> node's implementation, whether via an internal state variable, a custom input, or other method. + + + +* **`time`**: the current time in seconds, as defined by the host environment. This node must be of type float. Applications may use whatever method is appropriate to communicate the current time to the <time> node's implementation, whether via an internal state variable, a custom input, dividing the current frame number by a local "frames per second" value, or other method; real-time applications may return some variation of wall-clock time. + + + +* **`updirection`**: the current scene "up vector" direction, as defined by the shading environment. This node must be of type vector3. + * `space` (uniform string): the space in which to return the up vector direction, defaults to "world". + + + +## Standard Operator Nodes + +Operator nodes process one or more required input streams to form an output. Like other nodes, each operator must define its output type, which in most cases also determines the type(s) of the required input streams. + +``` + + + + + + + + + + + + +``` + +The inputs of compositing operators are called "fg" and "bg" (plus "alpha" for float and color3 variants, and "mix" for all variants of the `mix` operator), while the inputs of other operators are called "in" if there is exactly one input, or "in1", "in2" etc. if there are more than one input. If an implementation does not support a particular operator, it should pass through the "bg", "in" or "in1" input unchanged. + +This section defines the Operator Nodes that all MaterialX implementations are expected to support. Standard Operator Nodes are grouped into the following classifications: [Math Nodes](#math-nodes), [Adjustment Nodes](#adjustment-nodes), [Compositing Nodes](#compositing-nodes), [Conditional Nodes](#conditional-nodes), [Channel Nodes](#channel-nodes), [Convolution Nodes](#convolution-nodes) and [Shader Nodes](#shader-nodes). + + + +### Math Nodes + +Math nodes have one or two spatially-varying inputs, and are used to perform a math operation on values in one spatially-varying input stream, or to combine two spatially-varying input streams using a specified math operation. The given math operation is performed for each channel of the input stream(s), and the data type of each input must either match that of the input stream(s), or be a float value that will be applied to each channel separately. + + + + +* **`add`**: add a value to the incoming float/color/vector/matrix. See also the [Shader Nodes](#shader-nodes) section below for additional `add` variants supporting shader-semantic types. + * `in1` (float or colorN or vectorN or matrixNN): the value or nodename for the primary input + * `in2` (same type as `in1` or float): the value or nodename to add; for matrix types, the default is the zero matrix. + + + +* **`subtract`**: subtract a value from the incoming float/color/vector/matrix, outputting "in1-in2". + * `in1` (float or colorN or vectorN or matrixNN): the value or nodename for the primary input + * `in2` (same type as `in1` or float): the value or nodename to subtract; for matrix types, the default is the zero matrix + + + +* **`multiply`**: multiply an incoming float/color/vector/matrix by a value. Multiplication of two vectors is interpreted as a component-wise vector multiplication, while multiplication of two matrices is interpreted as a standard matrix product. To multiply a vector and a matrix, use one of the `transform*` nodes. See also the [Shader Nodes](#shader-nodes) section below for additional `multiply` variants supporting shader-semantic types. + * `in1` (float or colorN or vectorN or matrixNN): the value or nodename for the primary input + * `in2` (same type as `in1` or float): the value or nodename to multiply by; default is 1.0 in all channels for float/color/vector types, or the identity matrix for matrix types. + + + +* **`divide`**: divide an incoming float/color/vector/matrix by a value; dividing a channel value by 0 results in floating-point "NaN". Division of two vectors is interpreted as a component-wise division of the first vector by the second, while division of two matrices is interpreted as a standard matrix product of the `in1` matrix and the inverse of the `in2` matrix. + * `in1` (float or colorN or vectorN or matrixNN): the value or nodename for the primary input + * `in2` (same type as `in1` or float): the value or nodename to divide by; default is 1.0 in all channels for float/color/vector types, or the identity matrix for matrix types. + + + +* **`modulo`**: the remaining fraction after dividing an incoming float/color/vector by a value and subtracting the integer portion. Modulo always returns a non-negative result, matching the interpretation of the GLSL and OSL `mod()` function (not `fmod()`). + * `in1` (float or colorN or vectorN): the value or nodename for the primary input + * `in2` (same type as `in1` or float): the modulo value or nodename to divide by, cannot be 0 in any channel; default is 1.0 in all channels, which effectively returns the fractional part of a float value + + + +* **`absval`**: the per-channel absolute value of the incoming float/color/vector. + * `in` (float or colorN or vectorN): the input value or nodename + + + +* **`sign`**: the per-channel sign of the incoming float/color/vector value: -1 for negative, +1 for positive, or 0 for zero. + * `in` (float or colorN or vectorN): the input value or nodename + + + +* **`floor`**: the per-channel nearest integer value less than or equal to the incoming float/color/vector; the output remains in floating point per-channel, i.e. the same type as the input. + * `in` (float or colorN or vectorN): the input value or nodename + + + +* **`ceil`**: the per-channel nearest integer value greater than or equal to the incoming float/color/vector; the output remains in floating point per-channel, i.e. the same type as the input. + * `in` (float or colorN or vectorN): the input value or nodename + + + +* **`round`**: round each channel of the incoming float/color/vector values to the nearest integer value, e.g "floor(in+0.5)". + * `in` (float or colorN or vectorN): the input value or nodename + + + +* **`power`**: raise incoming float/color values to the specified exponent, commonly used for "gamma" adjustment. + * `in1` (float or colorN or vectorN): the value or nodename for the primary input + * `in2` (same type as `in` or float): exponent value or nodename; output = pow(in1, in2); default is 1.0 in all channels + + + +* **`sin`**: the sine of the incoming value, which is expected to be expressed in radians. + * `in` (float or vectorN): the input value or nodename + + + +* **`cos`**: the cosine of the incoming value, which is expected to be expressed in radians. + * `in` (float or vectorN): the input value or nodename + + + +* **`tan`**: the tangent of the incoming value, which is expected to be expressed in radians. + * `in` (float or vectorN): the input value or nodename + + + +* **`asin`**: the arcsine of the incoming value; the output will be expressed in radians. + * `in` (float or vectorN): the input value or nodename + + + +* **`acos`**: the arccosine of the incoming value; the output will be expressed in radians. + * `in` (float or vectorN): the input value or nodename + + + +* **`atan2`**: the arctangent of the expression (iny/inx); the output will be expressed in radians. If both `in1` and `in2` are provided, they must be the same type. + * `iny` (float or vectorN): the value or nodename for the "y" input; default is 0.0. + * `inx` (float or vectorN): the value or nodename for the "x" input; default is 1.0. + + + +* **`sqrt`**: the square root of the incoming value. + * `in` (float or vectorN): the input value or nodename + + + +* **`ln`**: the natural log of the incoming value. + * `in` (float or vectorN): the input value or nodename; default is 1.0. + + + +* **`exp`**: "e" to the power of the incoming value. + * `in` (float or vectorN): the input value or nodename + + + +* **`clamp`**: clamp incoming values per-channel to a specified range of float/color/vector values. + * `in` (float or colorN or vectorN): the input value or nodename + * `low` (same type as `in` or float): clamp low value; any value lower than this will be set to "low". Default is 0 in all channels. + * `high` (same type as `in` or float): clamp high value; any value higher than this will be set to "high". Default is 1 in all channels. + + + +* **`min`**: select the minimum of the two incoming values + * `in1` (float or colorN or vectorN): the first value or nodename + * `in2` (same type as `in1` or float): the second value or nodename + + + +* **`max`**: select the maximum of the two incoming values + * `in1` (float or colorN or vectorN): the first value or nodename + * `in2` (same type as `in1` or float): the second value or nodename + + + +* **`and`**: boolean "and" of the two incoming boolean values + * `in1` (boolean): the first value or nodename + * `in2` (boolean): the second value or nodename + + + +* **`or`**: boolean "or" of the two incoming boolean values + * `in1` (boolean): the first value or nodename + * `in2` (boolean): the second value or nodename + + + +* **`not`**: boolean "not" of the incoming boolean value + * `in` (boolean): the value or nodename + + + +* **`normalize`**: output the normalized vectorN from the incoming vectorN stream; cannot be used on float or colorN streams. Note: the fourth channel in vector4 streams is not treated any differently, e.g. not as a homogeneous "w" value. + * `in` (vectorN): the input value or nodename + + + +* **`magnitude`**: output the float magnitude (vector length) of the incoming vectorN stream; cannot be used on float or colorN streams. Note: the fourth channel in vector4 streams is not treated any differently, e.g. not as a homogeneous "w" value. + * `in` (vectorN): the input value or nodename + + + +* **`dotproduct`**: output the (float) dot product of two incoming vectorN streams; cannot be used on float or colorN streams. + * `in1` (vectorN): the input value or nodename for the primary input. + * `in2` (same type as `in1`): the secondary value or nodename + + + +* **`crossproduct`**: output the (vector3) cross product of two incoming vector3 streams; cannot be used on any other stream type. A disabled `crossproduct` node passes through the value of `in1` unchanged. + * `in1` (vector3): the input value or nodename for the primary input. + * `in2` (vector3): the secondary value or nodename + + + +* **`transformpoint`**: transform the incoming vector3 coordinate from one specified space to another; cannot be used on any other stream type. + * `in` (vector3): the input coordinate vector. + * `fromspace` (uniform string): the name of a vector space understood by the rendering target to transform the `in` point from; may be empty to specify the renderer's working or "common" space. + * `tospace` (uniform string): the name of a vector space understood by the rendering target for the space to transform the `in` point to. + + + +* **`transformvector`**: transform the incoming vector3 vector from one specified space to another; cannot be used on any other stream type. + * `in` (vector3): the input vector. + * `fromspace` (uniform string): the name of a vector space understood by the rendering target to transform the `in` point from; may be empty to specify the renderer's working or "common" space. + * `tospace` (uniform string): the name of a vector space understood by the rendering target for the space to transform the `in` point to. + + + +* **`transformnormal`**: transform the incoming vector3 normal from one specified space to another; cannot be used on any other stream type. + * `in` (vector3): the input normal vector; default is (0,0,1). + * `fromspace` (uniform string): the name of a vector space understood by the rendering target to transform the `in` point from; may be empty to specify the renderer's working or "common" space. + * `tospace` (uniform string): the name of a vector space understood by the rendering target for the space to transform the `in` point to. + + + +* **`transformmatrix`**: transform the incoming vectorN coordinate by the specified matrix. + * `in` (vectorN): the input vector. If needed, an additional 1.0 component will be temporarily appended to the `in` vector to make it match the dimension of the transforming `mat` matrix, then removed after transformation. + * `mat` matrix33/44): the matrix used to transform the vector; a vector2 `in` can be transformed by a matrix33, a vector3 by a matrix33 or a matrix44, and a vector4 by a matrix44. Default is the identity matrix. + + + +* **`transformcolor`**: transform the incoming color from one specified colorspace to another, ignoring any colorspace declarations that may have been provided upstream. For color4 types, the alpha channel value is unaffected. + * `in` (color3 or color4): the input color. + * `fromspace` (uniform string): the name of a standard colorspace or a colorspace understood by the application to transform the `in` color from; may be empty (the default) to specify the document's working colorspace. + * `tospace` (uniform string): the name of a standard colorspace or a colorspace understood by the application to transform the `in` color to; may be empty (the default) to specify the document's working colorspace. + + + +* **`normalmap`**: transform a normal vector from encoded tangent space to world space. The input normal vector is assumed to be encoded with all channels in the [0-1] range, as would commonly be output from a normal map. + * `in` (vector3): the input vector; default is (0.5, 0.5, 1.0). + * `scale` (float or vector2): a scalar multiplier for the (x,y) components of the incoming vector; defaults to 1.0 + * `normal` (vector3): surface normal; defaults to the current world-space normal. + * `tangent` (vector3): surface tangent vector, defaults to the current world-space tangent vector. + * `bitangent` (vector3): surface bitangent vector, defaults to the current world-space bitangent vector. + + + +* **`creatematrix`**: build a 3x3 or 4x4 matrix from three vector3 or four vector3 or vector4 inputs. A matrix44 may also be created from vector3 input values, in which case the fourth value will be set to 0.0 for in1-in3, and to 1.0 for in4 when creating the matrix44. + * `in1` (vector3 or vector4): the vector for the first row of the matrix. Default is (1,0,0) for matrix33 or (1,0,0,0) for matrix44. + * `in2` (vector3 or vector4): the vector for the second row of the matrix. Default is (0,1,0) for matrix33 or (0,1,0,0) for matrix44. + * `in3` (vector3 or vector4): the vector for the third row of the matrix. Default is (0,0,1) for matrix33 or (0,0,1,0) for matrix44. + * `in4` (vector3 or vector4): For matrix44 output type, the vector for the fourth row of the matrix. Default is (0, 0, 0, 1). + + + +* **`transpose`**: output the transpose of the incoming matrix. + * `in` (matrixNN): the input value or nodename + + + +* **`determinant`**: output the float determinant of the incoming matrixNN stream. + * `in` (matrixNN): the input value or nodename + + + +* **`invertmatrix`**: output the inverse of the incoming matrix; if the input matrix is not invertible, the output matrix will consist of all floating-point "NaN" values. + * `in` (matrixNN): the input value or nodename + + + +* **`rotate2d`**: rotate a vector2 value about the origin in 2D. + * `in` (vector2): the input value or nodename + * `amount` (float): the amount to rotate, specified in degrees, with positive values rotating the incoming vector counterclockwise. Default is 0. + + + +* **`rotate3d`**: rotate a vector3 value about a specified unit axis vector. + * `in` (vector3): the input value or nodename + * `amount` (float): the amount to rotate, specified in degrees; default is 0. + * `axis` (vector3): For vector3 inputs only, the unit axis vector about which to rotate; default is (0,1,0). + + + +* **`dot`**: a no-op, passes its input through to its output unchanged. Users can use dot nodes to shape edge connection paths or provide documentation checkpoints in node graph layout UI's. Dot nodes may also pass uniform values from <constant>, <tokenvalue> or other nodes with uniform="true" outputs to uniform <input>s and <token>s. + * `in` (any type): the nodename to be connected to the Dot node's "in" input. Unlike inputs on other node types, the <dot> node's input is specifically disallowed to provide a `channels` attribute: input data can only be passed through unmodified. + +Additional math nodes, including **``**, **``** and **``** may be found in the [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md#supplemental-math-nodes) document. + + + +### Adjustment Nodes + +Adjustment nodes have one input named "in", and apply a specified function to values in the incoming stream. + + + +* **`remap`**: linearly remap incoming values from one range of float/color/vector values to another. + * `in` (float or colorN or vectorN): the input value or nodename + * `inlow` (same type as `in` or float): low value for input range; default is 0.0 in all channels + * `inhigh` (same type as `in` or float): high value for input range; default is 1.0 in all channels + * `outlow` (same type as `in` or float): low value for output range; default is 0.0 in all channels + * `outhigh` (same type as `in` or float): high value for output range; default is 1.0 in all channels + + + +* **`smoothstep`**: output a smooth (hermite-interpolated) remapping of input values from low-high to output 0-1. + * `in` (float or colorN or vectorN): the input value or nodename + * `low` (same type as `in` or float): input low value; an input value of this or lower will result in an output value of 0; default is 0.0 in all channels + * `high` (same type as `in` or float): input high value; an input value of this or higher will result in an output value of 1; default is 1.0 in all channels + + + +* **`curveinversecubic`**: remap a 0-1 input float value using an inverse Catmull-Rom spline lookup on the input `knots` values. Outputs a 0-1 float interpolant value. + * `in` (float): the input value or nodename + * `knots` (uniform floatarray): the list of non-uniformly distributed input values defining the curve for the remapping. At least 2 values must be provided, and the first and last knot have multiplicity 2. + + + +* **`curveuniformlinear`**: output a float, colorN or vectorN value linearly interpolated between a number of `knotvalues` values, using the value of `in` as the interpolant. + * `in` (float): the input interpolant value or nodename + * `knotvalues` (uniform floatarray or colorNarray or vectorNarray): the array of at least 2 values to interpolate between. + + + +* **`curveuniformcubic`**: output a float, colorN or vectorN value smoothly interpolated between a number of `knotvalues` values using a Catmull-Rom spline with the value of `in` as the interpolant. + * `in` (float): the input interpolant value or nodename + * `knotvalues` (uniform floatarray or colorNarray or vectorNarray): the array of at least 2 values to interpolate between. + + + +* **`luminance`**: (color3 or color4 only) output a grayscale value containing the luminance of the incoming RGB color in all color channels, computed using the dot product of the incoming color with the luma coefficients of the working colorspace; the alpha channel is left unchanged if present. + * `in` (color3/color4): the input value or nodename + * `lumacoeffs` (uniform color3): the luma coefficients of the current working color space; if no specific color space can be determined, the ACEScg (ap1) luma coefficients [0.2722287, 0.6740818, 0.0536895] will be used. Applications which support color management systems may choose to retrieve the luma coefficients of the working colorspace from the CMS to pass to the <luminance> node's implementation directly, rather than exposing it to the user. + + + +* **`rgbtohsv`**: (color3 or color4 only) convert an incoming color from RGB to HSV space (with H and S ranging from 0 to 1); the alpha channel is left unchanged if present. This conversion is not affected by the current color space. + * `in` (color3/color4): the input value or nodename + + + +* **`hsvtorgb`**: (color3 or color4 only) convert an incoming color from HSV to RGB space; the alpha channel is left unchanged if present. This conversion is not affected by the current color space. + * `in` (color3/color4): the input value or nodename + +Additional adjustment nodes, including **``**, **``**, **``**, **``**, **``**, **``** and **``** may be found in the [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md#supplemental-adjustment-nodes) document. + + + +### Compositing Nodes + +Compositing nodes have two (required) inputs named `fg` and `bg`, and apply a function to combine them. Compositing nodes are split into five subclassifications: [Premult Nodes](#premult-nodes), [Blend Nodes](#blend-nodes), [Merge Nodes](#merge-nodes), [Masking Nodes](#masking-nodes), and the [Mix Node](#mix-node). + + +#### Premult Nodes + +Premult nodes operate on 4-channel (color4) inputs/outputs, have one input named `in`, and either apply or unapply the alpha to the float or RGB color. + + + +* **`premult`**: multiply the RGB channels of the input by the Alpha channel of the input. + * `in` (color4): the input value or nodename; default is (0,0,0,1). + + + +* **`unpremult`**: divide the RGB channels of the input by the Alpha channel of the input. If the Alpha value is zero, the original color4 input value is passed through unchanged. + * `in` (color4): the input value or nodename; default is (0,0,0,1). + + +#### Blend Nodes + +Blend nodes take two 1-4 channel inputs and apply the same operator to all channels (the math for alpha is the same as for R or RGB). In the Blend Operator table, "F" and "B" refer to any individual channel of the `fg` and `bg` inputs respectively. Blend nodes support an optional float input `mix`, which can be used to mix the original `bg` value (`mix`=0) with the result of the blend operation (`mix`=1, the default). + + +| Blend Operator | Each Channel Output | Supported Types | +| --- | --- | --- | +| **`plus`** | B+F | float, colorN | +| **`minus`** | B-F | float, colorN | +| **`difference`** | abs(B-F) | float, colorN | +| **`burn`** | 1-(1-B)/F | float, colorN | +| **`dodge`** | B/(1-F) | float, colorN | +| **`screen`** | 1-(1-F)(1-B) | float, colorN | +| **`overlay`** | 2FB if F<0.5;
1-(1-F)(1-B) if F>=0.5 | float, colorN | + + +#### Merge Nodes + +Merge nodes take two 4-channel (color4) inputs and use the built-in alpha channel(s) to control the compositing of the `fg` and `bg` inputs. In the Merge Operator table, "F" and "B" refer to the non-alpha channels of the `fg` and `bg` inputs respectively, and "f" and "b" refer to the alpha channels of the `fg` and `bg` inputs. Merge nodes are not defined for 1-channel or 3-channel inputs, and cannot be used on vectorN streams. Merge nodes support an optional float input `mix`, which can be used to mix the original `bg` value (`mix`=0) with the result of the blend operation (`mix`=1, the default). + + +| Merge Operator | RGB output | Alpha Output | +| --- | --- | --- | +| **`disjointover`** | F+B if f+b<=1;
F+B(1-f)/b if f+b>1 | min(f+b,1) | +| **`in`** | Fb | fb | +| **`mask`** | Bf | bf | +| **`matte`** | Ff+B(1-f) | f+b(1-f) | +| **`out`** | F(1-b) | f(1-b) | +| **`over`** | F+B(1-f) | f+b(1-f) | + + +#### Masking Nodes + +Masking nodes take one 1-4 channel input `in` plus a separate float `mask` input and apply the same operator to all channels (if present, the math for alpha is the same as for R or RGB). The default value for the `mask` input is 1.0 for the `inside` operator, and 0.0 for the `outside` operator In the Masking Operator table, "F" refers to any individual channel of the `in` input. + + +| Masking Operator | Each Channel Output | +| --- | --- | +| **`inside`** | Fm | +| **`outside`** | F(1-m) | + + +Note: for all types, `inside` is equivalent to the `multiply` node: both operators exist to provide companion functions for other data types or their respective inverse or complementary operations. + + +#### Mix Node + +The Mix node takes two 1-4 channel inputs `fg` and `bg` plus a separate 1-channel (float) or N-channel (same type and number of channels as `fg` and `bg`) `mix` input and mixes the `fg` and `bg` according to the mix value, either uniformly for a "float" `mix` type, or per-channel for non-float `mix` types. The equation for "mix" is as follows, with "F" and "B" referring to any channel of the `fg` and `bg` inputs respectively (which can be float, colorN or vectorN but must match), and "m" referring to the float `mix` input value (which has a default value of 0): + + +| Mix Operator | Each Channel Output | +| --- | --- | +| **`mix`** | Fm+B(1-m) | + + +See also the [Shader Nodes](#shader-nodes) section below for additional `mix` operator variants supporting shader-semantic types. + + + +### Conditional Nodes + +Conditional nodes are used to compare values of two streams, or to select a value from one of several streams. + + + + +* **`ifgreater`**: output the value of the `in1` or `in2` stream depending on whether the value of one test input is greater than the value of another. Ifgreater nodes can be of output type float, colorN or vectorN. There is also a "boolean" output-type **`ifgreater`** node, with `value1` and `value2` inputs but no `in1` or `in2`: output is "true" if `value1` > `value2`. + * `value1` (integer or float): the first value or nodename to compare. Default is 1.0. + * `value2` (integer or float): the second value or nodename to compare must be the same type as `value1`. Default is 0.0. + * `in1` (float or colorN or vectorN): the value or nodename to output if `value1` > `value2`; must be the same type as the `ifgreater` node's output. Default is 0.0. + * `in2` (float or colorN or vectorN): the value or nodename to output if `value1` <= `value2`; must be the same type as the `ifgreater` node's output. Default is 0.0. + + + +* **`ifgreatereq`**: output the value of the `in1` or `in2` stream depending on whether the value of one test input is greater than or equal to the value of another. Ifgreatereq nodes can be of output type float, colorN or vectorN. There is also a "boolean" output-type **`ifgreatereq`** node, with `value1` and `value2` inputs but no `in1` or `in2`: output is "true" if `value1` >= `value2`. + * `value1` (integer or float): the first value or nodename to compare. Default is 1.0. + * `value2` (integer or float): the second value or nodename to compare; must be the same type as `value1`. Default is 0.0. + * `in1` (float or colorN or vectorN): the value or nodename to output if `value1` >= `value2`; must be the same type as the `ifgreatereq` node's output. Default is 0.0. + * `in2` (float or colorN or vectorN): the value or nodename to output if `value1` < `value2`; must be the same type as the `ifgreatereq` node's output. Default is 0.0. + + + +* **`ifequal`**: output the value of the `in1` or `in2` stream depending on whether the value of two test inputs are equal or not. Ifequal nodes can be of output type float, colorN or vectorN. There is also a "boolean" output-type **`ifequal`** node, with `value1` and `value2` inputs but no `in1` or `in2`: output is "true" if `value1` == `value2`. + * `value1` (boolean or integer or float): the first value or nodename to compare. Default is 0 or "false". + * `value2` (boolean or integer or float): the second value or nodename to compare; must be the same type as `value1`. Default is 0 or "false". + * `in1` (float or colorN or vectorN): the value or nodename to output if `value1` == `value2`; must be the same type as the `ifequal` node's output. Default is 0.0. + * `in2` (float or colorN or vectorN): the value or nodename to output if `value1` != `value2`; must be the same type as the `ifequal` node's output. Default is 0.0. + + + +* **`switch`**: output the value of one of up to ten input streams, according to the value of a selector input `which`. Switch nodes can be of output type float, colorN or vectorN, and have five inputs, in1 through in10 (not all of which must be connected), which must match the output type. + * `in1`, `in2`, `in3`, `in4`, `in5`, `in6`, `in7`, `in8`, `in9`, `in10` (float or colorN or vectorN): the values or nodenames to select from based on the value of the `which` input. The types of the various `inN` inputs must match the type of the `switch` node itself. The default value of all `inN` inputs is 0.0 in all channels. + * `which` (integer or float): a selector to choose which input to take values from; the output comes from input "floor(`which`)+1", clamped to the 1-10 range. So `which`<1 will pass on the value from in1, 1<=`which`<2 will pass the value from in2, 2<=`which`<3 will pass the value from in3, and so on up to 9<=`which` will pass the value from in10. The default value of `which` is 0. + + + +* **`ifelse`**: output the value of one of two input streams, according to whether the value of a boolean selector input is true or false + * `infalse`, `intrue` (float or colorN or vectorN): the values or nodenames to select from based on the value of the `which` input. The types of the various `inN` inputs must match the type of the `switch` node itself. The default value of all `inN` inputs is 0.0 in all channels. + * `which` (boolean): a selector to choose which input to take values from; default is "false". + + + +### Channel Nodes + +Channel nodes are used to perform channel manipulations and data type conversions on streams. + + + + +* **`extract`**: extract the specified channel number from a colorN or vectorN stream. + * `in` (colorN or vectorN): the input value or nodename + * `which` (integer): the channel number to extract. For colorN streams, use "0" to extract the red channel, "1" for green, "2" for blue and "3" for alpha; for vectorN streams, use "0" to extract the x channel, "1" for y, "2" for z and "3" for w. Default is 0. + + + +* **`extractrowvector`**: extract the specified row vector number from a matrixN stream. + * `in` (matrixN): the input value or nodename + * `which` (integer): the row number to extract, should be 0-2 for matrix33 streams, or 0-3 for matrix44 streams. + + + +* **`convert`**: convert a stream from one data type to another. Only certain unambiguous and commonly-needed conversions are supported; see list below. + * `in` (boolean or integer or float or colorN or vectorN or string): the input value or nodename + + + + + +* **`combine2`**, **`combine3`**, **`combine4`**: combine the channels from two, three or four streams into the same total number of channels of a single output stream of a specified compatible type; please see the table below for a list of all supported combinations of input and output types. For color output types, no colorspace conversion will take place; the channels are simply copied as-is. + * `in1` (float/color3/vector2/vector3): the input value or nodename which will be sent to the N channels of the output; default is 0.0 in all channels + * `in2` (float/vector2): the input value or nodename which will be sent to the next N channels of the output; default is 0.0 in all channels + * `in3` (float): for **`combine3`** or **`combine4`**, the input value or nodename which will be sent to the next channel of the output after `in2`; default is 0.0 + * `in4` (float): for **`combine4`**, the input value or nodename which will be sent to the last channel of the output; default is 0.0 + + +The following input/output data type conversions are supported by **`convert`**: + +* float to colorN/vectorN: copy the input value to all channels of the output +* colorN to vectorN / vectorN to colorN, where _N_ is the same for in and out: straight copy of channel values +* color3 to color4: copy RGB, set output alpha to 1.0 +* color4 to color3: drop alpha channel +* boolean or integer to float: output is 0.0 or 1.0 +* vector2 to vector3, or vector3 to vector4: copy incoming channels and append an additional channel with value 1.0 (e.g. convert from non-homogeneous to homogeneous vector) +* vector3 to vector2, or vector4 to vector3: drop the last channel; if a homogeneous vector conversion is desired, use a **`divide`** node with `in1` connected to a `convert` node on the input to remove its last channel,and `in2` connected to the input with `channel="3"`. +* string to filename: no change in value + +Table of allowable input/output types for **`combine2`**, **`combine3`**, **`combine4`**: + + +| Operator | `type` | `in1` | `in2` | `in3` | `in4` | Output | +| --- | --- | --- | --- | --- | --- | --- | +| `combine2` | `vector2` | `float` "x" | `float` "y" | n/a | n/a | "xy" | +| `combine3` | `color3` | `float` "r" | `float` "g" | `float` "b" | n/a | "rgb" | +| `combine3` | `vector3` | `float` "x" | `float` "y" | `float` "z" | n/a | "xyz" | +| `combine4` | `color4` | `float` "r" | `float` "g" | `float` "b" | `float` "a" | "rgba" | +| `combine4` | `vector4` | `float` "x" | `float` "y" | `float` "z" | `float` "w" | "xyzw" | +| `combine2` | `color4` | `color3` "rgb" | `float` "a" | n/a | n/a | "rgba" | +| `combine2` | `vector4` | `vector3` "xyz" | `float` "w" | n/a | n/a | "xyzw" | +| `combine2` | `vector4` | `vector2` "xy" | `vector2` "zw" | n/a | n/a | "xyzw" | + + +Additional channel nodes, including **``** and **``**, may be found in the [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md#supplemental-channel-nodes) document. + + + +### Convolution Nodes + +Convolution nodes have one input named "in", and apply a defined convolution function on the input stream. Some of these nodes may not be implementable in ray tracing applications; they are provided for the benefit of purely 2D image processing applications. + + + + +* **`blur`**: a convolution blur. + * `in` (float or colorN or vectorN): the input value or nodename + * `size` (float): the size of the blur kernel, relative to 0-1 UV space; default is 0. + * `filtertype` (uniform string): the spatial filter used in the blur, either "box" for a linear box filter, or "gaussian" for a gaussian filter. Default is "box". + + + +* **`heighttonormal`**: convert a scalar height map to a normal map of type vector3. + * `in` (float): the input value or nodename + * `scale` (float): the scale of normal map deflections relative to the gradient of the height map. Default is 1.0. + * space (string): the space in which the output normal map vector should be; defaults to "tangent". + + + +### Shader Nodes + +Shader nodes construct a shader (a node with a shader semantic output type) from the specified inputs, which may then be connected to a material. Standard library shaders do not respond to external illumination; please refer to the [**MaterialX Physically Based Shading Nodes**](./MaterialX.PBRSpec.md#materialx-pbs-library) document for definitions of additional nodes and shader constructors which do respond to illumination. + + + + +* **`surface`**: Constructs a surface shader for an unlit surface with a plain unshaded color value. Useful for visualizing texture data or rendering non-PBR materials. Output type "surfaceshader". + * `color` (color3): Color value to display. Default is (0, 0, 0). + * `opacity` (float or color3): Cutout (float) or transmission (color3) opacity for the surface. Default is 1.0, representing a fully-opaque surface. + + + +* **`displacement`**: Constructs a displacement shader describing geometric modification to surfaces. Output type "displacementshader". + * `displacement` (float or vector3): Scalar (along the surface normal direction) or vector displacement (in (dPdu, dPdv, N) tangent/normal space) for each position. Default is 0. + * `scale` (float): Scale factor for the displacement vector. Default is 1.0. + + + +## Standard Node Inputs + +All standard nodes which define a `defaultinput` or `default` value support the following input: + + + +* `disable` (uniform boolean): if set to true, the node will pass its default input or value to its output, effectively disabling the node; default is false. Applications may choose to implement the `disable` input by skipping over the disabled node during traversal and instead passing through a connection to the defaultinput node or outputting the node's default value, rather than using an actual `disable` input in the node implementation. + + +## Standard UI Attributes + +All elements support the following additional UI-related attributes: + + + +* `doc` (string attribute): a description of the function or purpose of this element; may include standard HTML formatting strings such as <b>, <ul>, <p>, etc. but no complex formatting such as CSS or external references (e.g. no hyperlinks or images). May be used for functional documentation, or for UI pop-up "tool tip" strings. + + +All node types (sources, operators, shader nodes and material nodes) as well as <look> elements support the following UI-related attributes: + + + +* `xpos` (float attribute): X-position of the upper-left corner of the node when drawn in a UI. + + + +* `ypos` (float attribute): Y-position of the upper-left corner of the node when drawn in a UI. + + + +* `width` (float attribute): the relative width of the node when drawn in a UI; default is 1.0. + + + +* `height` (float attribute): the relative height of the node when drawn in a UI; default is 1.0. + + + +* `uicolor` (color3 attribute): the display-referred color of the node as drawn in the UI, normalized to 0.0-1.0 range; default is to not specify a particular color so the application's default node color would be used. `uicolor` values are expressed as color3 values in "none" colorspace, and thus are not affected by the current `colorspace`. + +All positioning and sizing attribute values are specified relative to an application's default size for drawing a node including any minimal-length connection edges and arrows. So a node drawn at position (xpos, ypos) will "look good" if connected to nodes drawn at position (xpos+width, ypos) and at position (xpos, ypos+height), and a node specifying `width="2"` would be drawn twice as wide (including outside whitespace for a minimal connecting arrow) as a node with the default width. It is not necessary that nodes be placed exactly on integer grid boundaries; this merely states the scale of nodes. It is also not assumed that the pixel scaling factors for X and Y are the same: the actual UI unit "grid" does not have to be square. If xpos and ypos are not both specified, placement of the node when drawn in a UI is undefined, and it is up to the application to figure out placement (which could mean "all piled up in the center in a tangled mess"). + +MaterialX defines xpos values to be increasing left to right, ypos values to be increasing top to bottom, and the general flow is generally downward. E.g. node inputs are on the top and outputs on the bottom, and a node at (10, 10) could connect naturally to a node at (10, 11). Content creation applications using left-to-right flow can simply exchange X and Y coordinates in their internal representations when reading or writing MaterialX data, and applications that internally use Y coordinates increasing upward rather than downward can invert the Y coordinates between MTLX files and their internal representations. + +The <input> and <token> elements within <nodedef>s and node instantiations (but not within <implementation>s or <nodegraph> parameter interfaces) support the following UI-related attributes: + + + +* `uivisible` (boolean attribute): whether or not the input is visible in the UI. If `uivisible` is specified on an input/token in a <nodedef> that defines the default visibility of that input/token, while a `uivisible` specified on a input/token in a node instantiation affects just the visibility of the input/token within that particular instantiation. Default is "true". + + + +* `uiadvanced` (boolean attribute): whether or not the input is considered to be an "advanced" parameter which an application may choose to hide in a more "basic" mode. Should normally be declared only within a <nodedef>. Default is "false", meaning the input should be displayed if `uivisible` is true, while "true" means the input would be displayed if `uivisible` is true and the application UI is set to show "advanced" parameters. + + + +## Backdrop Elements + +Backdrop elements are used to contain, group, and document nodes within a node graph, and they have no impact on the functionality of the graph. The following attributes are supported by <backdrop> elements: + +* `contains` (stringarray attribute): a comma-separated list of node names that the backdrop "contains"; default is to contain no nodes. +* `minimized` (boolean attribute): whether or not this backdrop is collapsed to a single node-sized box in the application's UI or not; default is false. + +Backdrop elements also support the standard `width`, `height`, `xpos`, `ypos` and `doc` attributes. + + + + +## Node Graph Examples + +#### Nodegraph Example 1 + +A simple merge of two single-layer images with a separate mask image, followed by a simple color operation. + +![Nodegraph Example 1](media/nodegraph1.png "Nodegraph Example 1") + +``` + + + + + + + + + + + + + + + + + + + + + + +``` + + +#### Nodegraph Example 2 + +A more complex nodegraph using geometry properties to define two diffuse albedo colors and two masks, then color-correcting one albedo less red and more blue and increasing the contrast of the other, blending the two through an area mask, and adding a small amount of scaled 2D Perlin noise within a second mask. The graph outputs the area mask layer separately from the composited diffuse albedo color. + +![Nodegraph Example 2](media/nodegraph2.png "Nodegraph Example 2") + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + +# Customization, Targeting and Shading + +While the Standard Nodes are considered universal across all MaterialX applications, there are many circumstances in which one would like to extend this with new custom functionality, or define functionality or underlying implementations specific to different applications or renderers. This includes the definition of nodes for shading and materials. + + +## Target Definition + +MaterialX supports the definition of nodes, attributes and inputs that are specific to particular rendering "targets". This allows a single implementation to restrict certain values or nodes to only the targets for which they are valid, or to allow separate definitions of the same node functionality for different renderers. + +Targets are declared using a <targetdef> element: + +``` + + + +``` + +A target may inherit from another target, so that any reference to a parent target will automatically include any definitions specific to the inherited child target that do not have a definition for the parent target itself: + +``` + + + +``` + +In the above example, any renderer that requests nodes/inputs/attributes for the "osl" target will also see any node/input/attribute that is defined with `target="oslpattern"`. A renderer may also declare that it will accept implementations for multiple targets, e.g. Vray might declare it will accept either "vrayosl", "mdl" or "vrayglsl", with "vrayosl" preferred. + +A targetdef element may also specify additional custom attributes for that target, such as configuration or code generation options. + + +## Custom Attributes and Inputs + +#### Custom Attributes + +While the MaterialX specification describes the attributes and elements that are meaningful to MaterialX-compliant applications, it is permissible to add custom attributes and inputs to standard MaterialX elements. These custom attributes and child elements are ignored by applications that do not understand them, although applications should preserve and re-output them with their values and connections even if they do not understand their meaning. + +If an application requires additional information related to any MaterialX element, it may define and utilize additional attributes with non-standard names. Custom attributes are defined using <attributedef> elements: + + +``` + +``` + +where _name_ is a unique name for the attributedef, _attrname_ is the name of the custom attribute to define, _type_ is the type of the attribute (typically string, stringarray, integer or boolean, although any MaterialX type is allowed), _defaultvalue_ is the default value for the attribute, _target_ is an optional list of targets to which this attribute applies, and _elements_ is an optional list of element names or elementname/inputname in which the attribute may be used. It is also permissible to provide enum and enumvalues attributes for an attributedef, to define specific labels and values that the custom attribute is allowed to take, using the same syntax and limitations as enum/enumvalues on nodedef inputs and tokens (see below). By default, a custom attribute is not emitted as metadata in generated shaders, but can be exported if the `exportable` attribute is set to "true". Examples: + +``` + + + +``` + +The first example above defines a 3ds Max-specific name attribute for surface materials, which may be given a value in addition to its MaterialX-compliant name in order to preserve the original package-specific name; it is assumed here that `maxmtlname` is the attribute name used by that particular implementation for this purpose. The second example defines a "mystudio"-specific boolean attribute "vflip", which could be used in the "file" input of <image> nodes. + +Once defined, custom attributes may be used in exactly the same manner as standard attributes: + +``` + + + + + + ... + +``` + + +#### Custom Inputs + +If an application requires additional custom inputs within a standard MaterialX node, it may define a target application-specific <nodedef> for that node inheriting the base input definitions from the standard node's <nodedef>, then add inputs specific to that target application. + +``` + + + +``` + +In the above example, a Maya-specific version of the color4-type <image> node has been declared, inheriting from the standard declaration then adding a maya-specific "preFilter" input. + +When using a node, the definition appropriate for the current target will automatically be used, and other targets will ignore any inputs that are not part of the nodedef for that target. However, one may specify a documentational `target` attribute on an input to hint what target it is intended for if desired. In this example, the "preFilter" input has indicated that it is specific to the "maya" target. + +``` + + + + +``` + + +## Custom Nodes + +Specific applications will commonly support sources and operators that do not map directly to standard MaterialX nodes. Individual implementations may provide their own custom nodes, with <nodedef> elements to declare their parameter interfaces, and <implementation> and/or <nodegraph> elements to define their behaviors. + + +### Custom Node Declaration NodeDef Elements + +Each custom node must be explicitly declared with a <nodedef> element, with child <input>, <token> and <output> elements specifying the expected names and types of the node’s inputs and output(s). + +Attributes for <nodedef> elements: + +* `name` (string, required): a unique name for this <nodedef> +* `node` (string, required): the name of the custom node being defined +* `inherit` (string, optional): the `name` of a <nodedef> to inherit node definitions from; the output types of this nodedef and the inherited one must match, and the input/output definitions of this nodedef will be applied on top of those in the inherited-from one. +* `nodegroup` (string, optional): an optional group to which this node declaration belongs. Standard MaterialX nodes have `nodegroup` values matching the titles of the section headings in which they are described, e.g. "texture2d", "procedural", "geometric", "global", "application", "math", "adjustment", "compositing", "conditional", "channel", "convolution", or "organization". +* `version` (string, optional): a version string for this nodedef, allowing usage of a node to reference a specific version of a node. Version strings should be of the format "_major_[._minor_]", i.e. one or two integer numbers separated by a dot (the minor version is assumed to be "0" if not provided). If there are multiple nodedefs for the same `node` and `target` with the same combination of input and output types, they must each specify a `version`. +* `isdefaultversion` (boolean, optional): If true, then this nodedef should be used for node instances which do not request a specific version. Specifying `isdefaultversion` "true" is only required if there are multiple nodedefs for a node declaring a `version`, and it is not permissible for multiple nodedefs for the same `node` and `target` with the same combination of input and output types to set `isdefaultversion` "true". Defaults to "false". +* `target` (stringarray, optional): the set of targets to which this nodedef is restricted. By default, a nodedef is considered universal, not restricted to any specific targets, but it is possible that certain targets may have different parameter names or usage for the same node. +* `uiname` (string, optional): an alternative "node" value for this nodedef to be displayed in the UI. If `uiname` is not provided, then `node` is the presumed UI node value for the nodedef. This is most useful when the <nodedef> defines a namespace, so the user doesn't need to see a full namespaced path for the node. +* `internalgeomprops` (stringarray, optional): a list of MaterialX geometric properties (e.g. "position", "normal", "texcoord", etc. or any name defined by a <geompropdef> element) that the node expects to be able to access internally. This metadata hint allows code generators to ensure this data is available and can be used for error checking. `Internalgeomprops` is most useful for nodes whose implementation is defined by external code; it is not necessary for nodegraph-defined nodes, as the list of geometric properties accessed can be determined by examining the nodegraph. + +Custom nodes are allowed to overload a single `node` name by providing multiple <nodedef> elements with different combinations of input and output types. This overloading is permitted both for custom `node` names and for the standard MaterialX node set. Within the scope of a single MaterialX document and its included content, no two <nodedef> elements with an identical combination of input and output types for the same target and version may be provided for a single `node` name. It is recommended that all <nodedef> variations for a `node` use exactly the same set of input names differing only in their types, with no variation adding or removing any inputs. It is also recommended that newer versions of nodes be fully backward-compatible with earlier versions (including default values of input) so that a change in default version of a node does not break functionality; if this is not possible, using a different `node` name is recommended. + +The `inherit` attribute may be provided to allow one <nodedef> to inherit from another: this is most useful for defining additional inputs in a target- or version-specific <nodedef>, inheriting from a generic, canonical definition of a node or shader. NodeDefs which inherit from another nodedef may not re-declare <output>s from the parent nodedef, only add additional new <output>s. + +NodeDefs must define one or more child <output> elements within the <nodedef> to state the name and type of each output; for nodes defined using a nodegraph, the names and types of the outputs must agree with the <output> elements in the nodegraph. The output name for a single-output <nodedef> is less important, as any connection made to the output of a single-output node will succeed regardless of the actual `name` referenced, although by convention, the name "out" is preferred for single-output nodes. See the [**NodeDef Output Elements**](#nodedef-output-elements) section below for details. + + +#### NodeDef Parameter Interface + +The parameter interface of a custom node is specified via a set of child <input> and <token> elements of the <nodedef>, while documentation of the folder structure of a node may be defined using a number of <uifolder> elements, each of which may provide a doc attribute to provide documentation for that folder layer. A <uifolder> element may not contain any other elements; in particular, the <input>s and <token>s of the nodedef interface must be direct children of the <nodedef>. Nested folders may be indicated using a full path for the folder, with a "/" separator between folder levels. + +``` + + + + + ...input and token definitions... + +``` + + +#### NodeDef Input Elements + +**Input** elements are used within a <nodedef> to declare the spatially-varying and uniform inputs for a node: + +``` + +``` + +Attributes for NodeDef Input elements: + +* `name` (string, required): the name of the shader input +* `type` (string, required): the MaterialX type of the shader input +* `value` (same type as `type`, optional): a default value for this input, to be used if the input remains unconnected and is not otherwise assigned a value +* `uniform` (boolean, optional): if set to "true", then this input can only take uniform values and may only be connected to the outputs of <constant> nodes or any other node whose output is explicitly declared to be "uniform" (optionally through a number of <dot> nodes), but not to the outputs of other (non-"uniform") nodes. `uniform` must be set to true for string and filename-type inputs. +* `defaultgeomprop` (string, optional): for vector2 or vector3 inputs, the name of an intrinsic geometric property that provides the default value for this input, must be one of "position", "normal", "tangent", "bitangent" or "texcoord" or vector3-type custom geometric property for vector3 inputs, or "texcoord" or vector2-type custom geometric property for vector2 inputs. For standard geometric properties, this is effectively the same as declaring a default connection of the input to a Geometric Node with default input values. May not be specified on uniform inputs. +* `enum` (stringarray, optional): a comma-separated non-exclusive list of string value descriptors that the input couldmayis allowed to take: for string- and stringarray-type inputs, these are the actual values (or values per array index for stringarrays); for other types, these are the "enum" labels e.g. as shown in the application user interface for each of the actual underlying values specified by `enumvalues`. The enum list can be thought of as a list of commonly used values or UI labels for the input rather than a strict list, and MaterialX itself does not enforce that a specified input enum value is actually in this list, with the exception that if the input is a "string" (or "stringarray") type and an enum list is provided, then the value(s) must in fact be one of the enum stringarray values. +* `enumvalues` (typearray, optional): for non-string/stringarray types, a comma-separated list of values of the same base type as the <input>, representing the values that would be used if the corresponding `enum` string was chosen in the UI. MaterialX itself does not enforce that a specified input value is actually in this list. Note that implementations are allowed to redefine `enumvalues` (but not `enum`) for specific targets: see the [Custom Node Definition Using Implementation Elements](#custom-node-definition-using-implementation-elements) section below. +* `colorspace` (string, optional): for color3- or color4-type inputs, the expected colorspace for this input. Nodedef inputs do not typically specify a colorspace; the most common use case is to specify `colorspace="none"` for inputs that are color-like but which should not be affected by colorspace conversions. +* `unittype` (string, optional): the type of unit for this input, e.g. "distance", which must be defined by a <unittypedef>. Default is to not specify a unittype. Only float-, vectorN- and filename-type inputs may specify a `unittype`. +* `unit` (string, optional): the specific unit for this input. Nodedef inputs do not typically specify a unit; if it does, that would indicate that the implementation of that node expects values to be specified in that unit, and that any invocation of that node using a different unit should be converted to the nodedef-specified unit for that input rather than to the application's scene unit. The most common instance of this is for angular values, where a nodedef might specify that it expects values to be given in degrees. +* `uiname` (string, optional): an alternative name for this input as it appears in the UI. If `uiname` is not provided, then `name` is the presumed UI name for the input. +* `uifolder` (attribute, string, optional): the pathed name of the folder in which this input appears in the UI, using a "/" character as a separator for nested UI folders. +* `uimin` (integer or float or colorN or vectorN, optional): for inputs of type integer, float, colorN or vectorN, the minimum value that the UI allows for this particular value. MaterialX itself does not enforce this as an actual minimum value. +* `uimax` (integer or float or colorN or vectorN, optional): for inputs of type integer, float, colorN or vectorN, the maximum value that the UI allows for this particular value. MaterialX itself does not enforce this as an actual maximum value. +* `uisoftmin` (integer or float or colorN or vectorN, optional): for inputs of type integer, float, colorN or vectorN, a suggested minimum UI slider value for this input, should be >= `uimin`. MaterialX itself does not enforce this as an actual minimum value. +* `uisoftmax` (integer or float or colorN or vectorN, optional): for inputs of type integer, float, colorN or vectorN, a suggested maximum UI slider value for this inputs, should be <= `uimax`. MaterialX itself does not enforce this as an actual maximum value. +* `uistep` (integer or float or colorN or vectorN, optional): for inputs of type integer, float, colorN or vectorN, the increment size that the UI would increment or decrement a component of the input value. +* `hint` (string): A hint to help code generators understand how the input may be used. The following hints for nodedef inputs are currently defined: + * "transparency": the input is indicating a level of shading transparency. + * "opacity": the input is indicating a level of shading opacity (inverse of transparency). + * "anisotropy": the presence of this hint on an input indicates that anisotropic reflections _may_ (but not necessarily) be taking place; if no input on a shading node(def) defines an "anisotropic" hint, then some implementations may use this as an optimization to allow only isotropic reflections. + +It is permissible to define a `value` or a `defaultgeomprop` for an input but not both. If neither `value` or `defaultgeomprop` are defined, then the input becomes required, and any invocation of the custom node without providing a value or connection for this input would be in error. + + +#### NodeDef Token Elements + +**Token** elements are used within a <nodedef> to declare uniform "interface token" string-substitution values to be referenced and substituted within filenames used in a node's nodegraph implementation: + +``` + +``` + +Attributes for NodeDef Token elements: + +* `name` (string, required): the name of the token +* `type` (string, required): the MaterialX type of the token; when the token's value is substituted into a filename, the token value will be cast to a string, so string or integer types are recommended for tokens, although any MaterialX type is permitted. +* `value` (same type as `type`, optional): a default value for this token, to be used if the node is invoked without a value defined for this token. If a default value is not defined, then the token becomes required, so any invocation of the custom node without a value assigned to that token would be in error. +* `enum` (stringarray, optional): a comma-separated non-exclusive list of string value descriptors that the token could take: for string-type tokens, these are the actual values; for other types, these are the "enum" labels e.g. as shown in the application user interface for each of the actual underlying values specified by enumvalues. The enum list can be thought of as a list of commonly used values or UI labels for the input rather than a strict list, and MaterialX itself does not enforce that a specified token enum value is actually in this list, with the exception that if the input is a "string" (or "stringarray") type and an enum list is provided, then the value(s) must in fact be one of the enum stringarray values. +* `enumvalues` (typearray, optional): for non-string types, a comma-separated list of values of the same base type as the <token>, representing the values that would be used if the corresponding enum string was chosen in the UI. MaterialX itself does not enforce that a specified token value is actually in this list. Note that implementations are allowed to redefine enumvalues (but not enum) for specific targets: see the [Custom Node Definition Using Implementation Elements](#custom-node-definition-using-implementation-elements) section below. +* `uiname` (string, optional): an alternative name for this token as it appears in the UI. If `uiname` is not provided, then `name` is the presumed UI name for the token. +* `uifolder` (string, optional): the pathed name of the folder in which this token appears in the UI, using a "/" character as a separator for nested UI folders. + +Please see the [Example Pre-Shader Compositing Material](#example-pre-shader-compositing-material) in the [Material Nodes](#material-nodes) section below for an example of how Tokens are used. + + +#### NodeDef Output Elements + +**Output** elements are used within a <nodedef> to declare an output for node definitions, including the output's name, type, and default value or "defaultinput" connection: + +``` + +``` + +Attributes for NodeDef Output elements: + +* `name` (string, required): the name of the output. For nodes with a single output, the name "out" is preferred. +* `type` (string, required): the MaterialX type of the output. +* `defaultinput` (string, optional): the name of an <input> element within the <nodedef>, which must be the same type as `type`, that will be passed through unmodified by applications that don’t have an implementation for this node. +* `default` (same type as `type`, optional): a constant value which will be output by applications that don’t have an implementation for this node, or if a `defaultinput` input is specified but that input is not connected. + +The <output> elements for NodeDefs are similar to those for NodeGraph outputs, except that they may define default output values for the node but may not define a connection to another node (except for the `defaultinput` pass-through connection declaration) or any output file-related attributes such as width, height, colorspace or bitdepth. + + + +### Custom Node Definition Using Implementation Elements + +Once the parameter interface of a custom node has been declared through a <nodedef>, MaterialX provides two methods for precisely defining its functionality: via an <implementation> element that references external source code, or via a <nodegraph> element that composes the required functionality from existing nodes. Providing a definition for a custom node is optional in MaterialX, but is recommended for maximum clarity and portability. + +**Implementation** elements are used to associate external function source code with a specific nodedef. Implementation elements support the following attributes: + +* `name` (string, required): a unique name for this <implementation> +* `nodedef` (string, required): the name of the <nodedef> for which this <implementation> applies +* `nodegraph` (string, optional): the name of the <nodegraph> which is the implementation for the specified nodedef; see the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section below. +* `implname` (string, optional): an alternative name for this node for the specified target; this allows one to say that for this particular target, the node/shader is called something else but is functionally equivalent to the node described by the nodedef. Note that node graphs in MaterialX documents should always use the node names defined in the nodedefs, never implementation-specific names. +* `file` (filename, optional): the URI of an external file containing the source code for the entry point of this particular node template. This file may contain source code for other templates of the same custom node, and/or for other custom nodes. +* `sourcecode` (string, optional): a string containing the actual source code for the node. +* `function` (string, optional): the name of a function within the given source code that contains the implementation of this node. If this attribute is not given it is assumed the source code is an inline expression for a shader code generator like ShaderGen. Please refer to appropriate language specifications and developer guides (such as the ShaderGeneration.md file in the GitHub documents/DeveloperGuide directory) for valid syntax for using inline code. +* `target` (stringarray, optional): the set of targets to which this implementation is restricted. By default, an implementation is considered applicable to all targets that the referenced nodedef applies to. If the referenced <nodedef> also specifies a target, then this `target` must be a subset of the nodedef's target list. +* `format` (string, optional): the format used by the given source code, typically "shader" if the source code is a complete shader that can be compiled and executed as is by a target renderer, or "fragment" if the source code is a code fragment that requires processing of a code generator before it can be compiled and executed. Default is "shader". + +An <implementation> may define a `file` or `sourcecode` attribute, or neither, but not both. If an <implementation> element specifies a `target` with no `file` or `sourcecode`, then it is interpreted purely as documentation that a private definition exists for the given target. Because the definition in an <implementation> may be restricted to specific targets, a <nodedef> that is defined with such restrictions may not be available in all applications; for this reason, a <nodedef> that is defined through an <implementation> is expected to provide a value for `default` and/or `defaultinput` when possible, specifying the expected behavior when no definition for the given node can be found. It should be noted that specifying `target` is intended to help applications differentiate between different implementations of nodes and implies compatibility for specific situations, but does not necessarily guarantee compatibility: they are intended to be hints about the particular implementation, and it is up to the host application to determine which <implementation>, if any, is appropriate for any particular use. + +Because the names used for node inputs (such as "normal" or "default") may conflict with the reserved words in various shading languages, or may simply be different for specific targets, <implementation> elements may contain a number of <input> elements to remap the `name`s of <input>s as specified in the <nodedef> to different `implname`s to indicate what the input name is actually called in the implementation's code. Only the inputs that need to be remapped to new `implname`s need to be listed; for each, it is recommended that the `type` of that input be listed for clarity, but if specified, it must match the type specified in the <nodedef>: <implementation>s are not allowed to change the type or any other attribute defined in the <nodedef>. In this example, the <implementation> declares that the "default" input defined in the "ND_image_color3" nodedef is actually called "default_value" in the "mx_image_color" function: + +``` + + + +``` + +For uniform inputs and tokens whose nodedef description includes an enum list of allowable values, individual implementations may associate different target-specific resolved values for them potentially of a different type; these may be described by providing an `enumvalues` attribute on the uniform input or token within an <implementation> and if appropriate, an `impltype` to declare the target-specific type of these enumvalues. Note that if the type of an enum input in the nodedef is an array type, then the `impltype` (if specified) must also be an array type, while `enumvalues` is a list of values of the base (non-array) type. The following <implementation> states that for the "mystudio" target, the uaddressmode and vaddressmode inputs of the "image" node are actually called "extrapolate_u" and "extrapolate_v", are integers rather than strings, and take different values (e.g. "clamp" is 2): + +``` + + + + + +``` + + +#### Implementation AOV Elements + +An <implementation> element with a file attribute defining an external compiled implementation of a surface shader may contain one or more <aov> elements to declare the names and types of arbitrary output variables ("AOVs") which the shader can output to the renderer. AOVs must be of type float, color3, vector3, BSDF or EDF. Note that in MaterialX, AOVs for pre-shading "pattern" colors are normally of type color3, while post-shaded color-like values are normally of type BSDF and emissive color-like values are normally of type EDF. An <implementation> with a `nodegraph` attribute may not contain <aov> elements; instead, <aovoutput> elements within the nodegraph should be used. + +``` + + ...... + + + +``` + +#### Example Custom Nodes Defined by External File Implementations + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +This example defines two templates for a custom operator node called "mariBlend" (one operating on color3 values, and one operating on floats), and one template for a custom source node called "mariCustomNoise". Implementations of these functions have been defined in both OSL and GLSL. There is also in this example an alternate implementation of the "mariCustomNoise" function specifically for VRay, as if the author had determined that the generic OSL version was not appropriate for that renderer. + +Here is an example of a two-output node definition and external implementation declaration. + +``` + + + + + + + +``` + + + +### Custom Node Definition Using Node Graphs + +Alternatively, a custom node's implementation may be described using a Node Graph. A <nodegraph> element wraps a graph of standard or custom nodes, taking the inputs and producing the output(s) described in the specified <nodedef>. + +A **<nodegraph>** element consists of at least one node element and at least one <output> element contained within a <nodegraph> element. Nodegraph elements may be one of two types: a **functional nodegraph**, which is the implementation of a node defined by a separate <nodedef>, or a **compound nodegraph**, which is a set of nodes grouped together into a nodegraph container. A functional nodegraph must either itself specify a `nodedef` attribute or be referenced by an <implementation> element with a "nodegraph" attribute, while a compound nodegraph may do neither but may optionally specify one or more <input> and/or <token> elements. + + +#### Functional Nodegraphs + +A **functional nodegraph** is a nodegraph-based implementation for a specified <nodedef>, with the <nodedef> declaring the set of inputs that the nodegraph accepts: a functional nodegraph may not itself specify any direct child input elements. + +``` + + ...node element(s)... + ...output element(s)... + +``` + +or + +``` + + ...node element(s)... + ...output element(s)... + + +``` + +The type(s) of the <output>(s) of the <nodedef> and the type(s) of the nodegraph <output>(s) must agree, and if there are multiple outputs, then the `name`s of the <output>s in the <nodegraph> and <nodedef> must also agree. The inputs and tokens of the <nodedef> can be referenced within <input> and <token> elements of nodes within the nodegraph implementation using `interfacename` attributes in place of `value` or `nodename` attributes, e.g. a nodedef input "i2" and interface token "diffmap" could be referenced as follows: + +``` + + +``` + +Note that a uniform <input> of a node within the nodegraph may use `interfacename` to reference a uniform input in the nodedef, but it may not reference a non-uniform nodedef input. + + +#### Compound Nodegraphs + +A **compound <nodegraph>** element may specify one or more child <input> and/or <token> elements. In this case, the <nodegraph> functions as a collapsible "wrapper" for the contained nodes. + +``` + + [...input and/or token element(s)...] + ...node and/or (compound) nodegraph element(s)... + ...output element(s)... + +``` + +A compound nodegraph provides a set of named input and output connection ports which may be referenced by its contained nodes using `interfacename` attributes, and interface token names whose values may be substituted into filenames used within the nodegraph; nodes within this <nodegraph> adopt the context of that nodegraph. The <input>s and <token>s of a compound nodegraph may also be connected to other nodes outside the <nodegraph> at the same scope as the <nodegraph> itself using `nodename` attributes; inputs of nodes within a compound nodegraph may only be connected to the outputs of other nodes within the same compound nodegraph, or to the input connection ports using interfacename. This is in contrast to a <backdrop> node whose contained nodes connect directly to nodes outside the backdrop at the same level of context without going through an intermediate named <input>. A <nodegraph> element of this form may specify the same float `width` and `height` and boolean `minimized` attributes as <backdrop> nodes. Inputs of other nodes, or the inputs of a compound nodegraph, can connect to an output of a (different) compound nodegraph using a `nodegraph` attribute (and for multiple-output compound nodegraphs, an `output` attribute as well) on a node's <input>. + +It is permissible to define multiple nodegraph- and/or file-based implementations for a custom node for the same combination of input and output types, as long as the specified `version`/`target`/`format` combinations are unique, e.g. one implementation for target "oslpattern" and another for "glsl", or one "osl" target with `format="shader"` and another with `format="fragment"`. It is allowable for there to be both a <nodegraph> and an <implementation> for the same nodedef target/version, with the <implementation> generally prevailing in order to allow for optimized native-code node implementations, although ultimately it would be up to the host application to determine which implementation to actually use. + + +#### Example Custom Node Defined by a Nodegraph + +``` + + + + + + + + + + + + + + + + + +``` + +The inputs of the nodegraph are declared by the <nodedef>, and the nodes within the nodegraph reference those inputs using `interfacename` attributes. The "fg" and "bg" inputs provide default values which are used if an input is left unconnected when the custom node is used, and the "amount" input defines a default value which will be used if invocations of the node do not explicitly provide a value for "amount". + + +### Custom Node Use + +Once defined with a <nodedef>, using a custom node within a node graph follows the same syntax as any other standard node: the name of the element is the name of the custom node, and the MaterialX type of the node's output is required; the custom node's child elements define connections of inputs to other node outputs as well as any input values for the custom node. + +``` + + + + + + + + + + +``` + +When invoking nodes with multiple outputs, the `type` of the node should be declared as "multioutput", and other node inputs connecting to an output of the node must include an `output` attribute to specify which output of the node to connect to: + +``` + + + + + + + + + + + + +``` + + + +## Shader Nodes + +Custom nodes that output data types with a "shader" semantic are referred to in MaterialX as "Shader Nodes". Shaders, along with their inputs, are declared using the same <nodedef>, <implementation> and <nodegraph> elements described above: + +``` + + ...input declarations... + + +``` + +The attributes for <nodedef> elements as they pertain to the declaration of shaders are: + +* `name` (string, required): a user-chosen name for this shader node definition element. +* `node` (string, required): the name of the shader node being defined, which typically matches the name of an associated shader function such as “blinn_phong”, “Disney_BRDF_2012”, “volumecloud_vol”. Just as for custom nodes, this shading program may be defined precisely through an <implementation> or <nodegraph>, or left to the application to locate by name using any shader definition method that it chooses. + +The child <output> element within the <nodedef> defines the "data type" of the output for this shader, which must have been defined with a "shader" semantic; see the [Custom Data Types](#custom-data-types) section above and discussion below for details. + +NodeDef elements defining shader nodes do not typically include `default` or `defaultinput` attributes, though they are permitted using the syntax described in the [Custom Data Types](#custom-data-types) section if the output type of the shader node is not a blind data type. + +As mentioned in the [Custom Data Types](#custom-data-types) section earlier, the standard MaterialX distribution includes the following standard data types for shaders: + +``` + + + + +``` + +These types all declare that they have "shader" semantic, but define different contexts in which a rendering target should interpret the output of the shader node. For a shading language based on deferred lighting computations (e.g. OSL), a shader-semantic data type is equivalent to a radiance closure. For a shading language based on in-line lighting computations (e.g. GLSL), a shader-semantic data type is equivalent to the final output values of the shader. + +Instantiation of shader nodes to give them specific values is done the same way as instantiating any other node type: + +``` + + + + + +``` + +Instantiated shader nodes can also inherit from other shader nodes of the same class: + +``` + + + +``` + +Declarations of shader node source implementations are accomplished using either <implementation> elements for external source file declarations, or functional nodegraphs for nodegraph-based definitions. + +As with non-shader custom nodes, **Input** elements are used within a <nodedef> to declare the input ports for a shader node. + +An input with a shader-semantic type may be given a value of "" to indicate no shader node is connected to this input; this is typically the default for shader-semantic inputs of operator nodes. It is up to applications to decide what to do with unconnected shader-semantic inputs. + + + +### Standard Shader-Semantic Operator Nodes + +The Standard MaterialX Library defines the following nodes and node variants operating on "shader"-semantic types. + +* **`mix`**: linear blend between two surface/displacement/volumeshader closures. + * `bg` (surface/displacement/volumeshader): the name of the background shader-semantic node + * `fg` (surface/displacement/volumeshader): the name of the foreground shader-semantic node + * `mix` (float): the blending factor used to mix the two input closures + +* **`surface_unlit`**: an unlit surface shader node, representing a surface that can emit and transmit light, but does not receive illumination from light sources or other surfaces. Output type surfaceshader. + * `emission` (float): the surface emission amount; default is 1.0 + * `emission_color` (color3): surface emission color; default is (1, 1, 1) + * `transmission` (float): the surface transmission amount; default is 0 + * `transmission_color` (color3): surface transmission color; default is (1, 1, 1) + * `opacity` (float): surface cutout opacity; default is 1.0 + + +### AOV Output Elements + +A functional nodegraph with either a "shader" or "material"-semantic output type may contain a number of <aovoutput> elements to declare arbitrary output variables ("AOVs") which the renderer can see and output as additional streams of information. AOVoutputs must be of type float, color3 or vector3 for pre-shading "pattern" values, or BSDF or EDF for shader-node output values; the renderer is expected to extract the appropriate color-like information from BSDF and EDF types. AOVs defined within a shader-semantic node instantiated within this functional nodegraph may be "passed along" and potentially renamed (but may not be modified or operated on in any way) by providing a sourceaov attribute in the <aovoutput>. + +``` + +``` + +The attributes for <aovoutput> elements are: + +* name (string, required): a user-chosen name for this aov output definition element. +* type (string, required): the type of the AOV, which must be one of the supported types listed above. +* aovname (string, required): the name that the renderer should use for the AOV. +* nodename (string, required): the name of the node whose output defines the AOV value. +* sourceaov (string, optional): If nodename is a surfaceshader type, the name of the output AOV defined within nodename to pass along as the output AOV. The type of the sourceaov defined within nodename must match the <aovoutput> type. + +Examples: + +``` + + + nodename="diffuse_bsdf"/> +``` + +#### AovOutput Example + +Example of using <aovoutput> with sourceaov to forward AOVs from within an instantiation of a shader-semantic node; this assumes that <standard_surface> has itself defined <aovoutput>s for "diffuse" and "specular" AOVs: + +``` + + + + + + + + + + + + + + + + + + + + + +``` + +Layered shaders or materials must internally handle blending of AOV-like values from source layers before outputting them as AOVs: there is currently no facility for blending AOVs defined within post-shading blended surfaceshaders. + +Note: while it is syntactically possible to create <aovoutput>s for geometric primitive values such as shading surface point and normal accessed within a nodegraph, it is preferred that renderers derive such information directly from their internal shading state or geometric primvars. + + + +## Material Nodes + +Custom nodes that output data types with a "material" semantic are referred to in MaterialX as "Material Nodes". Material nodes typically have one or more "shader" semantic inputs which establish what shaders the material references; previous versions of MaterialX used <shaderref> elements to establish these shader-to-material connections. Material Nodes are declared using the same <nodedef> elements as described above: + +``` + + + ...additional shader or input declarations... + + +``` + +The attributes for <nodedef> elements as they pertain to the declaration of materials are: + +* `name` (string, required): a user-chosen name for this material node definition element. +* `node` (string, required): the name of the material node class being defined. + +The standard MaterialX distribution includes a single material type definition used as the output type for all material nodes: + +``` + +``` + +as well as definitions for three standard material nodes, all outputting type "material": + + + +* **`surfacematerial`**: a surface shading material. + * `surfaceshader` (surfaceshader): the name of the surfaceshader node. + * `backsurfaceshader` (surfaceshader): the name of the surfaceshader node to be used for the back surface of an object, if the geometry is two-sided. Default is "", meaning the `surfaceshader` shader will be used for both sides of a surface if the geometry is two-sided. + * `displacementshader` (displacementshader): the name of the displacementshader node to use; default is "" for no displacement. + + + +* **`volumematerial`**: a volume shading material. + * `volumeshader` (volumeshader): the name of the volumeshader node. + + + +* **`lightmaterial`**: a light shader material. + * `lightshader` (lightshader): the name of the lightshader node. + +Material nodes supporting multiple shaders of the same type for different rendering targets can be defined: + +``` + + + + + + + + +``` + +Creating materials with specific values bound to shader inputs involves instantiating a Shader Node for each desired shader type and setting values on those shader nodes, and connecting the shader node(s) to the inputs of a Material Node: + +``` + + + + + + + + + + + +``` + +Alternatively, and perhaps more usefully, a complete network of multiple shader nodes of different types or for different targets along with a material node to collect them all can be packaged within a nodegraph, and the various inputs of the shader nodes and any other nodes connected to their inputs can be connected to a single material nodedef interface to provide parameter values for the entire multi-shader network. Because nodedef inputs can be referenced by more than one node, a single unified interface could be created for several shaders for different targets, and the networks for those targets could contain input value conversion nodes as needed to handle differences in parametrization or shading methodologies. + + +#### Material Inheritance + +Materials can inherit from other materials, to add or change shaders connected to different inputs; in this example, a displacement shader is added to the above "Mgold" material to create a new "Mgolddsp" material: + +``` + + + + + + + + + + + +``` + +Inheritance of material-type custom nodes is also allowed, so that new or changed input values can be applied on top of those specified in the inherited material. + +#### Example Pre-Shader Compositing Material + +A material to blend between three different surface layers using mask textures. This example also demonstrates the use of the "target" attribute of a shader implementation element to define multiple renderer-specific shaders of the same type referenced within a single material, and the use of interface tokens to define texture filenames. + +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + +## Material Variants + +A Variant is a container for any number of uniform values for material inputs and interface tokens. One or more mutually-exclusive variants are defined as part of a <variantset>; variants may not be defined outside of a <variantset>. + +``` + + + + + + + ...additional declarations for this variantset... + +``` + +<Input> elements within a <variant> may only define a `value`, not a connection to a node or <output>. + +Example uses for variants include defining a number of allowable colors and texture tokens for different costume variations, and defining values for progressively increasing levels of damage to a model. + +Variants and variantsets are not intrinsically associated with any particular material; they merely state a number of values for a number of named inputs/tokens. However, variantsets may state that they are associated with specific shader-semantic nodes and/or <nodedef> declarations by providing stringarray-type `node` and/or `nodedef` attributes: + +``` + + ... + + ... +``` + +Variants and variantsets can be defined in any MaterialX implementation, but because variants are applied to materials within a <look>, they can only be applied in applications supporting MaterialX Geometry Extensions; please see the [**VariantAssign Elements**](./MaterialX.GeomExts.md#variantassign-elements) section in that document for information on using material variants. + + +# References + +[^1]: + diff --git a/documents/Specification/inprog_v1.39/MaterialX.Supplement.md b/documents/Specification/inprog_v1.39/MaterialX.Supplement.md new file mode 100644 index 0000000000..703fa1275c --- /dev/null +++ b/documents/Specification/inprog_v1.39/MaterialX.Supplement.md @@ -0,0 +1,493 @@ + + + +# MaterialX: Supplemental Notes + +**Version 1.39** +Doug Smythe - Industrial Light & Magic +Jonathan Stone - Lucasfilm Advanced Development Group +March 25, 2023 + + + +# Introduction + +This document details additional information about MaterialX and how it may be incorporated into studio pipelines. The document describes a number of additional Supplemental Nodes providing enhanced functionality over the basic Standard Nodes, as well as a recommended naming convention for node definition elements and a directory structure to define packages of node definitions and implementations from various sources. + + + +## Table of Contents + +**[Introduction](#introduction)** + +**[Supplemental Nodes](#supplemental-nodes)** + [Supplemental Texture Nodes](#supplemental-texture-nodes) + [Supplemental Procedural Nodes](#supplemental-procedural-nodes) + [Supplemental Math Nodes](#supplemental-math-nodes) + [Supplemental Adjustment Nodes](#supplemental-adjustment-nodes) + [Supplemental Channel Nodes](#supplemental-channel-nodes) + +**[Recommended Element Naming Conventions](#recommended-element-naming-conventions)** + +**[Material and Node Library File Structure](#material-and-node-library-file-structure)** + [Examples](#examples) + +**[Definitions, Assets, and Libraries](#definitions-assets-and-libraries)** + [Organization Using Node Graphs](#organization-using-node-graphs) + [Publishing Definitions](#publishing-definitions) + [Dependencies and Organization](#dependencies-and-organization) + [Deployment, Transmission, and Translation](#deployment-transmission-and-translation) + + + +# Supplemental Nodes + +The MaterialX Specification defines a number of Standard Nodes, which all implementations of MaterialX are expected to support, to the degree their host applications allow. These nodes are the basic "building blocks" upon which more complex node functionality can be built. + +This section describes a number of supplemental nodes for MaterialX. These nodes are considered part of MaterialX, but are typically implemented using graphs of standard MaterialX nodes rather than being implemented for specific targets. Certain applications may choose to implement these supplemental nodes using native coding languages for efficiency. It is also expected that various applications will choose to extend these supplemental nodes with additional parameters and additional functionality. + + +### Supplemental Texture Nodes + + + +* **`tiledimage`**: samples data from a single image, with provisions for tiling and offsetting the image across uv space. + * `file` (uniform filename): the URI of an image file. The filename can include one or more substitutions to change the file name (including frame number) that is accessed, as described in [Filename Substitutions in the main Specification document](./MaterialX.Specification.md#filename-substitutions). + * `default` (float or colorN or vectorN): a default value to use if the `file` reference can not be resolved (e.g. if a <geomtoken>, [interfacetoken] or {hostattr} is included in the filename but no substitution value or default is defined, or if the resolved file URI cannot be read), or if the specified `layer` does not exist in the file. The `default` value must be the same type as the `` element itself. If `default` is not defined, the default color value will be 0.0 in all channels. + * `texcoord` (vector2): the name of a vector2-type node specifying the 2D texture coordinate at which the image data is read. Default is to use the current u,v coordinate. + * `uvtiling` (vector2): the tiling rate for the given image along the U and V axes. Mathematically equivalent to multiplying the incoming texture coordinates by the given vector value. Default value is (1.0, 1.0). + * `uvoffset` (vector2): the offset for the given image along the U and V axes. Mathematically equivalent to subtracting the given vector value from the incoming texture coordinates. Default value is (0.0, 0.0). + * `realworldimagesize` (vector2): the real-world size represented by the `file` image, with unittype "distance". A `unit` attribute may be provided to indicate the units that `realworldimagesize` is expressed in. + * `realworldtilesize` (vector2): the real-world size of a single square 0-1 UV tile, with unittype "distance". A `unit` attribute may be provided to indicate the units that `realworldtilesize` is expressed in. + * `filtertype` (uniform string): the type of texture filtering to use; standard values include "closest" (nearest-neighbor single-sample), "linear", and "cubic". If not specified, an application may use its own default texture filtering method. + + ``` + + + + + + + ``` + + + +* **`triplanarprojection`**: samples data from three images (or layers within multi-layer images), and projects a tiled representation of the images along each of the three respective coordinate axes, computing a weighted blend of the three samples using the geometric normal. + * `filex` (uniform filename): the URI of an image file to be projected in the direction from the +X axis back toward the origin. + * `filey` (uniform filename): the URI of an image file to be projected in the direction from the +Y axis back toward the origin with the +X axis to the right. + * `filez` (uniform filename): the URI of an image file to be projected in the direction from the +Z axis back toward the origin. + * `layerx` (uniform string): the name of the layer to extract from a multi-layer input file for the x-axis projection. If no value for `layerx` is provided and the input file has multiple layers, then the "default" layer will be used, or "rgba" if there is no "default" layer. Note: the number of channels defined by the `type` of the `` must match the number of channels in the named layer. + * `layery` (uniform string): the name of the layer to extract from a multi-layer input file for the y-axis projection. + * `layerz` (uniform string): the name of the layer to extract from a multi-layer input file for the z-axis projection. + * `default` (float or colorN or vectorN): a default value to use if any `fileX` reference can not be resolved (e.g. if a <geomtoken>, [interfacetoken] or {hostattr} is included in the filename but no substitution value or default is defined, or if the resolved file URI cannot be read) The `default` value must be the same type as the `` element itself. If `default` is not defined, the default color value will be 0.0 in all channels. + * `position` (vector3): a spatially-varying input specifying the 3D position at which the projection is evaluated. Default is to use the current 3D object-space coordinate. + * `normal` (vector3): a spatially-varying input specifying the 3D normal vector used for blending. Default is to use the current object-space surface normal. + * `filtertype` (uniform string): the type of texture filtering to use; standard values include "closest" (nearest-neighbor single-sample), "linear", and "cubic". If not specified, an application may use its own default texture filtering method. + + ``` + + + + + + + ``` + + +### Supplemental Procedural Nodes + + + +* **`ramp4`**: a 4-corner bilinear value ramp. + * `valuetl` (float or colorN or vectorN): the value at the top-left (U0V1) corner + * `valuetr` (float or colorN or vectorN): the value at the top-right (U1V1) corner + * `valuebl` (float or colorN or vectorN): the value at the bottom-left (U0V0) corner + * `valuebr` (float or colorN or vectorN): the value at the bottom-right (U1V0) corner + * `texcoord` (vector2, optional): the name of a vector2-type node specifying the 2D texture coordinate at which the ramp interpolation is evaluated. Default is to use the first set of texture coordinates. + + + +* **`unifiednoise2d`**: a single node supporting 2D Perlin, Cell, Worley or Fractal noise in a unified interface. + * `type` (integer): The type of noise function to use. One of 0 (Perlin), 1 (Cell), 2 (Worley), or 3 (Fractal); default is Perlin. + * `texcoord` (vector2): the input 2d space. Default is the first texture coordinates. + * `freq` (vector2): Adjusts the noise frequency, with higher values producing smaller noise shapes. Default is (1,1). + * `offset` (vector2): Shift the noise in 2d space. Default is (0,0). + * `jitter` (float): Adjust uniformity of Worley noise; for other noise types jitters the results. + * `outmin` (float): The lowest values fit to the noise. Default is 0.0. + * `outmax` (float): The highest values fit to the noise. Default is 1.0. + * `clampoutput` (boolean): Clamp the output to the min and max output values. + * `octaves` (integer): The number of octaves of Fractal noise to be generated. Default is 3. + * `lacunarity` (float): The exponential scale between successive octaves of Fractal noise. Default is 2.0. + * `diminish` (float): The rate at which noise amplitude is diminished for each octave of Fractal noise. Default is 0.5. + + + +* **`unifiednoise3d`**: a single node supporting 3D Perlin, Cell, Worley or Fractal noise in a unified interface. + * `type` (integer): The type of noise function to use. One of 0 (Perlin), 1 (Cell), 2 (Worley), or 3 (Fractal); default is Perlin. + * `position` (vector3): the input 3d space. Default is position in object-space. + * `freq` (vector3): Adjusts the noise frequency, with higher values producing smaller noise shapes. Default is (1,1,1). + * `offset` (vector3): Shift the noise in 3d space. Default is (0,0,0). + * `jitter` (float): Adjust uniformity of Worley noise; for other noise types jitters the results. + * `outmin` (float): The lowest values fit to the noise. Default is 0.0. + * `outmax` (float): The highest values fit to the noise. Default is 1.0. + * `clampoutput` (boolean): Clamp the output to the min and max output values. + * `octaves` (integer): The number of octaves of Fractal noise to be generated. Default is 3. + * `lacunarity` (float): The exponential scale between successive octaves of Fractal noise. Default is 2.0. + * `diminish` (float): The rate at which noise amplitude is diminished for each octave of Fractal noise. Default is 0.5. + + + +### Supplemental Math Nodes + + + +* **`place2d`**: transform incoming UV texture coordinates for 2D texture placement. + * `texcoord` (vector2): the input UV coordinate to transform; defaults to the current surface index=0 uv coordinate. + * `pivot` (vector2): the pivot coordinate for scale and rotate: this is subtracted from u,v before applying scale/rotate, then added back after. Default is (0,0). + * `scale` (vector2): divide the u,v coord (after subtracting `pivot`) by this, so a scale (2,2) makes the texture image appear twice as big. Negative values can be used to flip or flop the texture space. Default is (1,1). + * `rotate` (float): rotate u,v coord (after subtracting pivot) by this amount in degrees, so a positive value rotates UV coords counter-clockwise, and the image clockwise. Default is 0. + * `offset` (vector2): subtract this amount from the scaled/rotated/“pivot added back” UV coordinate; since U0,V0 is typically the lower left corner, a positive offset moves the texture image up and right. Default is (0,0). + * `operationorder` (integer enum): the order in which to perform the transform operations. "0" or "SRT" performs -pivot scale rotate translate +pivot as per the original implementation matching the behavior of certain DCC packages, and "1" or "TRS" performs -pivot translate rotate scale +pivot which does not introduce texture shear. Default is 0 "SRT" for backward compatibility. + + + +* **`safepower`**: raise incoming float/color values to the specified exponent. Unlike the standard <power> node, negative `in1` values for <safepower> will result in negative output values, e.g. `out = sign(in1)*pow(abs(in1),in2)`. + * `in1` (float or colorN or vectorN): the value or nodename for the primary input + * `in2` (same type as `in` or float): exponent value or nodename; default is 1.0 in all channels + + + +* **`triplanarblend`**: samples data from three inputs, and projects a tiled representation of the images along each of the three respective coordinate axes, computing a weighted blend of the three samples using the geometric normal. + * inx (float or colorN): the image to be projected in the direction from the +X axis back toward the origin. Default is 0 in all channels. + * iny (float or colorN): the image to be projected in the direction from the +Y axis back toward the origin with the +X axis to the right. Default is 0 in all channels. + * inz (float or colorN): the image to be projected in the direction from the +Z axis back toward the origin. Default is 0 in all channels. + * position (vector3): a spatially-varying input specifying the 3D position at which the projection is evaluated. Default is to use the current 3D object-space coordinate. + * normal (vector3): a spatially-varying input specifying the 3D normal vector used for blending. Default is to use the current object-space surface normal. + * filtertype (uniform string): the type of texture filtering to use; standard values include "closest" (nearest-neighbor single-sample), "linear", and "cubic". If not specified, an application may use its own default texture filtering method. + + + +### Supplemental Adjustment Nodes + + + +* **`contrast`**: increase or decrease contrast of incoming float/color values using a linear slope multiplier. + * `in` (float or colorN or vectorN): the input value or nodename + * `amount` (same type as `in` or float): slope multiplier for contrast adjustment, 0.0 to infinity range. Values greater than 1.0 increase contrast, values between 0.0 and 1.0 reduce contrast. Default is 1.0 in all channels. + * `pivot` (same type as `in` or float): center pivot value of contrast adjustment; this is the value that will not change as contrast is adjusted. Default is 0.5 in all channels. + + + +* **`range`**: remap incoming values from one range of float/color/vector values to another, optionally applying a gamma correction "in the middle". Input values below `inlow` or above `inhigh` are extrapolated unless `doclamp` is true, in which case the output values will be clamped to the `outlow`..`outhigh` range. + * `in` (float or colorN or vectorN): the input value or nodename + * `inlow` (same type as `in` or float): low value for input range. Default is 0.0 in all channels. + * `inhigh` (same type as `in` or float): high value for input range. Default is 1.0 in all channels. + * `gamma` (same type as `in` or float): inverse exponent applied to input value after first transforming from `inlow`..`inhigh` to 0..1; `gamma` values greater than 1.0 make midtones brighter. Default is 1.0 in all channels. + * `outlow` (same type as `in` or float): low value for output range. Default is 0.0 in all channels. + * `outhigh` (same type as `in` or float): high value for output range. Default is 1.0 in all channels. + * `doclamp` (boolean): If true, the output is clamped to the range `outlow`..`outhigh`. Default is false. + + + +* **`hsvadjust`**: adjust the hue, saturation and value of an RGB color by converting the input color to HSV, adding amount.x to the hue, multiplying the saturation by amount.y, multiplying the value by amount.z, then converting back to RGB. A positive "amount.x" rotates hue in the "red to green to blue" direction, with amount of 1.0 being the equivalent to a 360 degree (e.g. no-op) rotation. Negative or greater-than-1.0 hue adjustment values are allowed, wrapping at the 0-1 boundaries. For color4 inputs, the alpha value is unchanged. + * `in` (color3 or color4): the input value or nodename + * `amount` (vector3): the HSV adjustment; a value of (0, 1, 1) is "no change" and is the default. + + + +* **`saturate`**: (color3 or color4 only) adjust the saturation of a color; the alpha channel will be unchanged if present. Note that this operation is **not** equivalent to the "amount.y" saturation adjustment of `hsvadjust`, as that operator does not take the working or any other colorspace into account. + * `in` (float or colorN or vectorN): the input value or nodename + * `amount` (float): a multiplier for saturation; the saturate operator performs a linear interpolation between the luminance of the incoming color value (copied to all three color channels) and the incoming color value itself. Note that setting amount to 0 will result in an R=G=B gray value equal to the value that the `luminance` node (below) returns. Default is 1.0. + * `lumacoeffs` (uniform color3): the luma coefficients of the current working color space; if no specific color space can be determined, the ACEScg (ap1) luma coefficients [0.272287, 0.6740818, 0.0536895] will be used. Applications which support color management systems may choose to retrieve this value from the CMS to pass to the <saturate> node's implementation directly, rather than exposing it to the user. + + + +* **`colorcorrect`**: Combines various adjustment nodes into one artist-friendly color correction node. For color4 inputs, the alpha value is unchanged. + * `in` (color3 or color4): the input color to be adjusted. + * `hue` (float): Rotates the color hue, with values wrapping at 0-1 boundaries; default is 0. + * `saturation` (float): Multiplies the input color saturation level; default is 1. + * `gamma` (float): Applies a gamma correction to the color; default is 1. + * `lift` (float): Raise the dark color values, leaving the white values unchanged; default is 0. + * `gain` (float): Multiplier increases lighter color values, leaving black values unchanged; default is 1. + * `contrast` (float): Linearly increase or decrease the color contrast; default is 1. + * `contrastpivot` (float): Pivot value around which contrast applies. This value will not change as contrast is adjusted; default is 0.5. + * `exposure` (float): Multplier which increases or decreases color brightness by 2^value; default is 0. + + + +* **`curveadjust`**: output a smooth remapping of input values using the centripetal Catmull-Rom cubic spline curve defined by specified knot values, using an inverse spline lookup on input knot values and a forward spline through output knot values. All channels of the input will be remapped using the same curve. + * `in` (float or colorN or vectorN): the input value or nodename + * `numknots` (uniform integer): the number of values in the knots and knotvalues arrays + * `knots` (uniform floatarray): the list of input values defining the curve for the remapping. At least 2 and at most 16 values must be provided. + * `knotvalues` (uniform floatarray): the list of output values defining the curve for the remapping. Must be the same length as knots. + + + +* **`curvelookup`**: output a float, colorN or vectorN value smoothly interpolated between a number of knotvalue values, using the position of in within knots as the knotvalues interpolant. + * `in` (float): the input interpolant value or nodename + * `numknots` (uniform integer): the number of values in the knots and knotvalues arrays + * `knots` (uniform floatarray): the list of knot values to interpolate in within. At least 2 and at most 16 values must be provided. + * `knotvalues` (uniform floatarray or colorNarray or vectorNarray): the values at each knot position to interpolate between. Must be the same length as knots. + + + +### Supplemental Channel Nodes + + + +* **`separate2`**: output each of the channels of a vector2 as a separate float output. + * `in` (vector2): the input value or nodename + * `outx` (**output**, float): the value of x channel. + * `outy` (**output**, float): the value of y channel. + + + +* **`separate3`**: output each of the channels of a color3 or vector3 as a separate float output. + * `in` (color3 or vector3): the input value or nodename + * `outr`/`outx` (**output**, float): the value of the red (for color3 streams) or x (for vector3 streams) channel. + * `outg`/`outy` (**output**, float): the value of the green (for color3 streams) or y (for vector3 streams) channel. + * `outb`/`outz` (**output**, float): the value of the blue (for color3 streams) or z (for vector3 streams) channel. + + + +* **`separate4`**: output each of the channels of a color4 or vector4 as a separate float output. + * `in` (color4 or vector4): the input value or nodename + * `outr`/`outx` (**output**, float): the value of the red (for color4 streams) or x (for vector4 streams) channel. + * `outg`/`outy` (**output**, float): the value of the green (for color4 streams) or y (for vector4 streams) channel. + * `outb`/`outz` (**output**, float): the value of the blue (for color4 streams) or z (for vector4 streams) channel. + * `outa`/`outw` (**output**, float): the value of the alpha (for color4 streams) or w (for vector4 streams) channel. + + + +* **`separatecolor4`**: output the RGB and alpha channels of a color4 as separate outputs. + * `in` (color4): the input value or nodename + * `outcolor` (output, color3): the RGB channel values. + * `outa` (output, float): the value of the alpha channel. + + + +# Recommended Element Naming Conventions + +While MaterialX elements can be given any valid name as described in the MaterialX Names section of the main specification, adhering to the following recommended naming conventions will make it easier to predict the name of a nodedef for use in implementation and nodegraph elements as well as help reduce the possibility of elements from different sources having the same name. + +**Nodedef**: "ND\__nodename_\__outputtype_[\__target_][\__version_]", or for nodes with multiple input types for a given output type (e.g. <convert>), "ND\__nodename_\__inputtype_\__outputtype_[\__target_][\__version_]". + +**Implementation**: "IM\__nodename_[\__inputtype_]\__outputtype_[\__target_][\__version_]". + +**Nodegraph**, as an implementation for a node: "NG\__nodename_[\__inputtype_]\__outputtype_[\__target_][\__version_]". + + + +# Material and Node Library File Structure + +As studios and vendors develop libraries of shared definitions and implementations of MaterialX materials and nodes for various targets, it becomes beneficial to have a consistent, logical organizational structure for the files on disk that make up these libraries. In this section, we propose a structure for files defining libraries of material nodes, <nodedef>s, nodegraph implementations and actual target-specific native source code, as well as a mechanism for applications and MaterialX content to find and reference files within these libraries. + +Legend for various components within folder hierarchies: + +| Term | Description | +| --- | --- | +| _libname_ | The name of the library; the MaterialX Standard nodes are the "stdlib" library. Libraries may choose to declare themselves to be in the libname namespace, although this is not required. | +| _target_ | The target for an implementation, e.g. "glsl", "oslpattern", "osl" or "mdl". | +| _sourcefiles_ | Source files (including includes and makefiles) for the target, in whatever format and structure the applicable build system requires. | + + +Here is the suggested structure and naming for the various files making up a MaterialX material or node definition library setup. Italicized terms should be replaced with appropriate values, while boldface terms should appear verbatim. The optional "\_\*" component of the filename can be any useful descriptor of the file's contents, e.g. "\_ng" for nodegraphs or "\_mtls" for materials. + + + _libname_/_libname_**\_defs.mtlx** (1) + _libname_/_libname_\_\***.mtlx** (2) + _libname_/_target_/_libname_\_target[\_\*]**\_impl.mtlx** (3) + _libname_/_target_/_sourcefiles_ (4) + + + +1. Nodedefs and other definitions in library _libname_. +2. Additional elements (e.g. nodegraph implementations for nodes, materials, etc.) in library _libname_. +3. Implementation elements for _libname_ specific to target _target_. +4. Source code files for _libname_ implementations specific to target _target_. + +Note that nodedef files and nodegraph-implementation files go at the top _libname_ level, while <implementation> element files go under the corresponding _libname_/_target_ level, next to their source code files. This is so that studios may easily install only the implementations that are relevant to them, and applications can easily locate the implementations of nodes for specific desired targets. Libraries are free to add additional arbitrarily-named folders for related content, such as an "images" subfolder for material library textures. + +The _libname_\_defs.mtlx file typically contains nodedefs for the library, but may also contain other node types such as implementation nodegraphs, materials, looks, and any other element types. The use of additional _libname_\_\*.mtlx files is optional, but those files should be Xincluded by the _libname_\_defs.mtlx file. + +A file referenced by a MaterialX document or tool (e.g. XInclude files, filenames in <image> or other MaterialX nodes, or command-line arguments in MaterialX tools) can be specified using either a relative or a fully-qualified absolute filesystem path. A relative path is interpreted to be relative to either the location of the referencing MaterialX document itself, or relative to a location found within the current MaterialX search path: this path may be specified via an application setting (e.g. the `--path` option in MaterialXView) or globally using the MATERIALX_SEARCH_PATH environment variable. These search paths are used for both XIncluded definitions and filename input values (e.g. images for nodes or source code for <implementation>s), and applications may choose to define different search paths for different contexts if desired, e.g. for document processing vs. rendering. + +The standard libraries `stdlib` and `pbrlib` are typically included _automatically_ by MaterialX applications, rather than through explicit XInclude directives within .mtlx files. Non-standard libraries are included into MaterialX documents by XIncluding the top-level _libname_/_libname_\_defs.mtlx file, which is expected to in turn XInclude any additional .mtlx files needed by the library. + + +### Examples + +In the examples below, MXROOT is a placeholder for one of the root paths defined in the current MaterialX search path. + +A library of studio-custom material shading networks and example library materials: + +``` + MXROOT/mtllib/mtllib_defs.mtlx (material nodedefs and nodegraphs) + MXROOT/mtllib/mtllib_mtls.mtlx (library of materials using mtllib_defs) + MXROOT/mtllib/images/*.tif (texture files used by mtllib_mtls nodes) +``` + +Documents may include the above library using + +``` + +``` + +and that file would XInclude `mtllib_mtls.mtlx`. <Image> nodes within `mtllib_mtls.mtlx` would use `file` input values such as "images/bronze_color.tif", e.g. relative to the path of the `mtllib_mtls.mtlx` file itself. + +Standard node definitions and reference OSL implementation: + +``` + MXROOT/stdlib/stdlib_defs.mtlx (standard library node definitions) + MXROOT/stdlib/stdlib_ng.mtlx (supplemental library node nodegraphs) + MXROOT/stdlib/osl/stdlib_osl_impl.mtlx (stdlib OSL implementation elem file) + MXROOT/stdlib/osl/*.{h,osl} (etc) (stdlib OSL source files) +``` + +Layout for "genglsl" and "genosl" implementations of "stdlib" for MaterialX's shadergen component, referencing the above standard `stdlib_defs.mtlx` file: + +``` + # Generated-GLSL implementations + MXROOT/stdlib/genglsl/stdlib_genglsl_impl.mtlx (stdlib genGLSL implementation file) + MXROOT/stdlib/genglsl/stdlib_genglsl_cm_impl.mtlx (stdlib genGLSL color-mgmt impl. file) + MXROOT/stdlib/genglsl/*.{inline,glsl} (stdlib common genGLSL code) + + # Generated-OSL implementations + MXROOT/stdlib/genosl/stdlib_genosl_impl.mtlx (stdlib genOSL implementation file) + MXROOT/stdlib/genosl/stdlib_genosl_cm_impl.mtlx (stdlib genOSL color-mgmt impl. file) + MXROOT/stdlib/genosl/*.{inline,osl} (stdlib common genOSL code) +``` + +Layout for the shadergen PBR shader library ("pbrlib") with implementations for "genglsl" and "genosl" (generated GLSL and OSL, respectively) targets: + +``` + MXROOT/pbrlib/pbrlib_defs.mtlx (PBR library definitions) + MXROOT/pbrlib/pbrlib_ng.mtlx (PBR library nodegraphs) + MXROOT/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx (pbr impl file referencing genGLSL source) + MXROOT/pbrlib/genglsl/*.{inline,glsl} (pbr common genGLSL code) + MXROOT/pbrlib/genosl/pbrlib_genosl_impl.mtlx (pbr impl file referencing genOSL source) + MXROOT/pbrlib/genosl/*.{inline,osl} (pbr common genOSL code) +``` + + + +# Definitions, Assets, and Libraries + +In this section we propose a set of guidelines for managing unique definitions or assets and organization into libraries, wherein: + +* Definitions: Correspond directly to <nodedefs> which may or be either source code implementations or based on existing node definitions. +* Assets: is a term which corresponds to a definition plus any additional metadata on a definition and /or related resources such as input images. These can be organized in logical groupings based on a desired semantic. +* Libraries: are a collection of assets. + + +### Organization Using Node Graphs + +While it is possible to just have a set of connected nodes in a document, it is not possible to have any formal unique interface. This can invariably lead to nodes which have duplicate names, the inability to control what interfaces are exposed and inability to maintain variations over time. + +Thus the base requirement for a definition is to encapsulate the nodes into a <nodegraph>. This provides for: + +1. Hiding Complexity: Where all nodes are scoped with the graph. For user interaction point, it makes possible the ability to “drill down” into a graph as needed but otherwise a black box representation can be provided. +2. Identifier / Path Uniqueness : The nodegraph name decreases the chances of name clashes. For example two top level nodes both called “foo” would have unique paths “bar1/foo” and “bar2/foo” when placed into two nodegraphs “bar1” and “bar2”. +3. Interface / node signature control where specific inputs may be exposed via “interfacename” connections and outputs as desired. This differs from “hiding” inputs or outputs which do not change the signature. The former enforces what is exposed to the user while the latter are just interface hints. + +For individual inputs it is recommended to add the following additional attributes as required: + +1. Real World Units : If an input value depends on scene / geometry size then a unit attribute should always be added. For example if the graph represents floor tile, then to place it properly the size of the tile. A preset set of “distance” units is provided as part of the standard library. +2. Colorspace: If an input value is represented in a given color space then to support proper transformation into rendering color space this attribute should be set. A preset set of colorspace names conforming to the AcesCg 1.2 configuration is provided as part of the standard library. + +Though not strictly required it is very useful to have appropriate default values as without these the defaults will be zero values. Thus for example a “scale” attribute for a texture node should not be left to default to zero. + + +### Publishing Definitions + +From a <nodegraph> a definition can be (new <nodedef>) created or “published”. Publishing allows for the following important capabilities: + +1. Reuse: The ability to reuse an unique node definition as opposed to duplicating graph implementations. +2. Variation: The ability to create or apply variations to an instance independent from the implementation. +3. Interoperability: Support definitions with common properties that are mutually understood by all consumers be exchanged. + +In order to support these capabilities It is recommended that the following attributes always be specified: + +1. A unique name identifier: This can follow the ND\_ and NG\_ convention described. It is recommended that the signature of the interface also be encoded to provide uniqueness, especially if the definition may be polymorphic. +2. A namespace identifier (\*): When checking uniqueness namespace is always used so it is not required to be part of the name identifier to provide uniqueness. + * It should not be used as it will result in the namespace being prepended multiple times. E.g. a “foo” node with a namespace “myspace” has a unique identifier of “myspace:node”. If the node is named “myspace:node”, then the resulting identifier is “myspace:myspace:node”. + * Note that import of a Document will prepend namespaces as required without namespace duplication. +3. A version identifier: While this can be a general string, it is recommended that this be a template with a specific format to allow for known increment numbering. E.g. The format may be “v#.#” to support minor and major versioning. This requires that only one out of all versions be tagged as the default version. Care should be taken to ensure this as the first one found will be used as the default. +4. A nodegroup identifier: This can be one mechanism used for definition organization, or for user interface presentation. It is also used for shader generation to some extent as it provides hints as to the type of node. For example <image> nodes are in the “texture2d” node group. +5. A documentation string. Though not strictly required this provides some ability to tell what a node does, and can be used as a user interface helper. Currently there is no formatting associated with this but it is possible to embed a format. + +Note that utilities which codify publishing logic are provided as part of the core distribution. + +To support variation it is proposed that both <token>s and <variant>s be used. + + + +1. Tokens: These allow for the sample “template” be used for filenames with having to create new definitions. This can reduce the number of required definitions but also reduce the number of presets required. For example tokens can be used to control the format, resolution of the desired filename identifier. +2. Variants and Variant Sets: There are no hard-and-fast “rules” for when to create a definition vs use a definition with variants but one possible recommendation is to use variants when there are no interface signature differences (_Discuss_?). Some advantages include the fact that variants may be packaged and deployed independent of definitions and/or new definitions do not need to be deployed per variation. Note that for now only value overrides are possible. + + +### Dependencies and Organization + +The more definitions are added including those based on other definitions, the harder it can be to discover what definitions are required given documents with some set of node instances. + +To support separability of dependents, the following logical high level semantic breakdown is proposed: + + + +1. Static “Core” library definitions. These include stdlib, pbrlib and bxdf. The recommendation is to always load these in and assume that they exist. For separability, it is recommended that these all be stored in a single runtime Document. +2. Static custom library definitions. These are based on core libraries. The recommendation is to not directly reference any core libraries using the Xinclude mechanism. This can result in duplicate possibly conflicting definitions being loaded. The “upgrade” mechanism will ensure that all core and custom libraries are upgraded to the appropriate target version. For separability, it is recommended that these all be stored in a single runtime Document. +3. Dynamically created definitions. If this capability is allowed then it can be useful to have a fixed set of locations that these definitions can update. This could be local to the user or to update an existing custom library. + +Additional groupings can be added to provide semantic organization (such as by “nodegroup”) though the recommendation is that they live within a common library root or package. + +For an asset with dependent resources there are many options. Two of which are: + + + +1. Co-locate resources with the definition. This allows for easier “packaging” of a single asset such as for transmission purposes but this can require additional discovery logic to find resources associated with a definition and may result in duplication of resources. +2. Located in a parallel folder structure to definitions. The onus is to maintain this parallel structure but the search logic complexity is the same for resources as it is for definitions. + +If a definition is a source code implementation, then additional path search logic is required for discoverability during generation. + +The following search paths are available: + + + +* MATERIALX_SEARCH_PATH: This environment variable is used as part of both definition and resource search (e.g. relative filename path support). +* Source code paths: This can be registered at time of code generation as part of the generation “context”. It is recommended to follow the source path locations which would be relative to any custom definitions, using the “language” identifier of the code generator to discover the appropriate source code files. + +An example usage of pathing can be found in the sample Viewer. The logic is as follows: + + + +* The module/binary path is set as the default “root” definition path. Additional definition roots are included via MATERIALX_SEARCH_PATH. +* The set of roots are considered to be the parent of “resources” and “libraries” folders, for resource and definitions respectively. +* The search path root for resources would be the “`/resources`” by default. This allows for handling of resources which are part of an assets definition. For example a brick shader located at “`/myroot/shaders/brick.mtlx`” may have the brick textures referenced at location “`/myroot/textures/brick.exr`”. Setting a single search path to “`/myroot`” handles the “parallel” folder organization mentioned, with the relative reference being “`textures/brick.exr`” +* For any shader at a given path a path to that shader can be added when resolving dependent resources. This can be used to handle the co-located folder organization. For example the shader may reside in “`/myroot/shader/brick.mtlx`”, and the texture in “`/myroot/shader/textures/brick.exr`”. Setting a root to “`myroot/shader`” and a relative reference to “`textures/brick.exr`” will allow for proper discovery. + +For runtime, it is recommended that instead of reading in documents that they be “imported”. This allows for mechanisms such as namespace handling as well as tagging of source location (“sourceURI”) to occur per document. At some point all dependent documents need to be merged into a single one as there is no concept of referenced in-memory documents. Tagging is a useful mechanism to allow filtering out / exclusion of definitions from the main document content. For example, the main document can be “cleared” out while retaining the library definitions. + +As there may be definitions dependent on other definitions, it is never recommended to unload core libraries, and care be taken when unloading custom or dynamic libraries. It may be useful to re-load all definitions if there is a desire to unload any one library. + +Note that code generation is context based. If the context is not cleared, then dependent source code implementations will be retained. It is recommended to clear implementations if definitions are unloaded. + + +### Deployment, Transmission, and Translation + +Given a set of definitions it is useful to consider how it will be deployed. + +Some deployments for which file access may be restricted or accessing many files is a performance issue, pre-package up definitions, source and associated resources may be required. For example, this is currently used for the sample Web viewer deployment. + +Some deployments may not want to handle non-core definitions or may not be able to handle (complex) node graphs. Additionally the definition may be transmitted as a shader. Thus, when creating a new definition it is recommended to determine the level of support for: + + + +1. Flattening: Can the definition be converted to a series of nodes which have source code implementations. +2. Baking: Can the definition be converted to an image. +3. Translation: Can the implementation be converted mapped / converted to another implementation which can be consumed. +4. Shader Reflection: Can the desired metadata be passed to the shader for introspection. + +Additional metadata which is not a formal part of the specification may lead to the inability to be understood by consumers. + diff --git a/documents/Specification/inprog_v1.39/README_v1.39.md b/documents/Specification/inprog_v1.39/README_v1.39.md new file mode 100644 index 0000000000..f63017ba9d --- /dev/null +++ b/documents/Specification/inprog_v1.39/README_v1.39.md @@ -0,0 +1,120 @@ + + +**MaterialX** is an open standard for representing rich material and look-development content in computer graphics, enabling its platform-independent description and exchange across applications and renderers. MaterialX addresses the need for a common, open standard to represent the data values and relationships required to describe the look of a computer graphics model, including shading networks, patterns and texturing, complex nested materials and geometric assignments. To further encourage interchangeable CG look setups, MaterialX also defines a large set of standard shading and processing nodes with a precise mechanism for functional extensibility. + +The documents in this folder comprise the complete MaterialX Specification, version 1.39. + +* [**MaterialX Specification**](./MaterialX.Specification.md) - the main Specification, describing definitions, core functionality and the standard node library +* [**MaterialX Physically Based Shading Nodes**](./MaterialX.PBRSpec.md) - describes BSDF and other shading function nodes useful in constructing complex layered rendering shaders using node graphs +* [**MaterialX Geometry Extensions**](./MaterialX.GeomExts.md) - additional MaterialX elements to define geometry-related information such as collections, properties and material assignments +* [**MaterialX Supplemental Notes**](./MaterialX.Supplement.md) - describes a number of additional node types built from the standard nodes as well as recommended naming and structuring conventions for libraries of custom node definitions + +

+ +--- + + +**MaterialX v1.39** provides the following enhancements over v1.38: + + +**MaterialX Geometry Extensions** + +The parts of the main MaterialX Specification document dealing with various Geometry-related features has now been split into a separate [**MaterialX Geometry Extensions**](./MaterialX.GeomExts.md) document, describing Collections, Geometry Name Expressions, geometry-related data types, Geometry Info elements and the GeomProp and Token elements used within them, and Look, Property, Visibility and assignment elements. + +With this split, applications can claim to be MaterialX Compatible if they support all the things described in the main Specification, e.g. the elements for nodegraph shading networks and materials as well as the standard set of nodes, while using an application's native mechanisms or something like USD to describe the assignment of these materials to geometry. Applications may additionally support the MaterialX Geometry Extensions and thus use a single unified representation for complete CG objecct looks. + + +**New Support for Shader AOVs** + +Previously, MaterialX used custom types with a structure of output variables to define shader AOVs. But this approach was not very flexible and in fact had not been implemented. In v1.39, nodegraph-based shader implementations can include new [<aovoutput> elements](./MaterialX.Specification.md#aov-output-elements) to define AOVs which renderers can use to output additional channels of information in addition to the final shading result, while file-based <implementation>s can similarly define AOVs using [<aov> elements](./MaterialX.Specification.md#implementation-aov-elements). + + +**Array Types Now Uniform and Static Length** + +Many shading languages do not support dynamic array types with a variable length, so MaterialX now only supports arrays with a fixed maximum length, and all array-type node inputs must be uniform; nodes are no longer permitted to output an array type. Array-type inputs may be accompanied by a uniform integer input declaring the number of array elements actually used in the array. Because of this change, the unimplemented <arrayappend> node has been removed. + + +**Connectable Uniform Inputs and New Tokenvalue Node** + +A uniform node input is now explicitly allowed to be connected to the output of a <constant> node. This makes it possible to define a uniform value and use it in multiple places in a nodegraph. + +Similarly, <token>s in materials and other node instances may now be connected to the output of a new <tokenvalue> node: this is essentially a <constant> node but which connects to <token>s rather than <input>s. + + +**Standardized Color Space Names** + +The [standard colorspace names](./MaterialX.Specification.md#color-spaces-and-color-management-systems) in MaterialX have now been defined explicitly in the Specification, and are aligned to their definitions in the ACES 1.2 OCIO config file. With this change, there is no need for a definition of "cms" or "cmsconfig" in MaterialX documents, so those two attributes have been deprecated. + + +**Disambiguated Nodedef and Nodegraph References** + +Normally, the set of provided inputs to a node and their types in conjunction with the output type of the node itself is sufficient to disambiguate exactly which nodedef signature should be applied. In the rare situations where this is not sufficient, it is now permissible for any node instantiation to specify the name of a nodedef to completely disambiguate the intended node signature. + +Additionally, a <nodegraph> could previously declare itself to be an implementation of a particular <nodedef> by providing a "nodedef" attribute, which is still the preferred method for making this association. Now, it is also permissible for an [<implementation> element](39/MaterialX.Specification.md#custom-node-definition-using-implementation-elements) to provide a "nodegraph" attribute to declare that nodegraph to be the implementation for the nodedef specified in the <implementation>. This allows a single nodegraph to be the implementation of multiple nodedefs, e.g. two different node names with the same underlying implementation, or if the only difference between two versions of a nodedef is the default values. + + +**Generalized Swizzle Operator Removed** + +The standard <swizzle> node using a string of channel names and allowing arbitrary channel reordering is very inefficient (and in some shading languages virtually impossible) to implement as previously specified, and as such has been removed. Nodegraphs should instead use combinations of <extract> (which is now a standard node), <separateN> and <combineN> nodes to perform arbitrary channel reordering. Additionally, the previous "channels" attribute for inputs which allowed arbitrary channel reordering and used string "swizzle" channel naming has been replaced with an integer "channel" attribute, allowing a float input to be connected to a specified channel number of a colorN or vectorN output. This is both far more efficient to implement and more closely matches the conventions for connecting different input and output types available in modern DCCs. + + +**New Unlit Surface Shader and Standard Materials** + +A new standard <surface> constructor node for unlit surfaces has been added to the standard library. + +Additionally, the standard <surfacematerial> material now supports both single- or double-sided surfaces with the addition of a separate `backsurface` input. + + +**Inheritance and Hints for Typedefs** + +Typedefs may now inherit from other types, including built-in types, and may provide hints about their values such as floating-point precision. These new "inherit" and "hint" attributes are themselves merely metadata hints about the types; applications and code generators are still expected to provide their own precise definitions for all custom types. + + +**New Nodes** + +The following new standard operator nodes have been added: + +* [Procedural nodes](./MaterialX.Specification.md#procedural-nodes): **tokenvalue**, **fractal2d**, **cellnoise1d** +* [Geometric nodes](./MaterialX.Specification.md#geometric-nodes): **bump**, **geompropvalueuniform** +* [Math nodes](./MaterialX.Specification.md#math-nodes): boolean **and**, **or**, **not**; **transformcolor**, **creatematrix** +* [Adjustment nodes](./MaterialX.Specification.md#adjustment-nodes): **curveinversecubic**, **curveuniformlinear** and **curveuniformcubic** +* [Conditional nodes](./MaterialX.Specification.md#conditional-nodes): boolean-output variants of **ifgreater**, **ifgreatereq** and **ifequal**; new **ifelse** node +* [Channel nodes](./MaterialX.Specification.md#channel-nodes): **extractrowvector** + +Additionally, the following new supplemental nodes have been added: + +* [Procedural nodes](./MaterialX.Supplement.md#supplemental-procedural-nodes): **unifiednoise2d**, **unifiednoise3d** +* [Math nodes](./MaterialX.Supplement.md#supplemental-math-nodes): **triplanarblend** +* [Adjustment nodes](./MaterialX.Supplement.md#supplemental-adjustment-nodes): **colorcorrect** +* [Channel nodes](./MaterialX.Supplement.md#supplemental-channel-nodes): **separatecolor4** + + +**New Physically Based Shading Nodes** + +The following new standard physically based shading nodes have been added: + +* [EDF nodes](./MaterialX.PBRSpec.md#edf-nodes): **generalized_schlick_edf** +* [Shader nodes](./MaterialX.PBRSpec.md#shader-nodes): **environment** (latlong environment light source) + + +**Other Changes** + +* The <member> element for <typedef>s and the "member" attribute for inputs have been removed from the Specification, as they had never been implemented and it was not clear how they could be implemented generally. +* The "valuerange" and "valuecurve" attributes describing expressions and function curves have been removed, in favor of using the new <curveinversecubic> / <curveuniformcubic> / etc. nodes. +* The <cellnoise2d> and <cellnoise3d> nodes now support vectorN output types in addition to float output. +* The <worleynoise2d> and <worleynoise3d> nodes now support a number of different distance metrics. +* The <time> node no longer has a "frames per second" input: the application is now always expected to generate the "current time in seconds" using an appropriate method. "Fps" was removed because varible-rate real-time applications have no static "fps", and it's generally not good to bake a situation-dependent value like fps into a shading network. +* A standard "tangent" space is now defined in addition to "model", "object" and "world" spaces, and the <heighttonormal> node now accepts a uniform "space" input to define the space of the output normal vector. +* The <surface> and <displacement> nodes are now part of the main Specification rather than being Physically Based Shading nodes. +* <Token> elements are now explicitly allowed to be children of compound nodegraphs, and token values may now have defined enum/enumvalues. +* Inputs in <nodedef>s may now supply "hints" to code generators as to their intended interpretation, e.g. "transparency" or "opacity". +* <Attributedef> elements may now define enum/enumvalues to list acceptable values or labels/mapped values for an attribute. +* If a string input specifies an "enum" list, the list is now considered a "strict" list of allowable values; no values are allowed outside that list. To make the input non-strict, one must omit the "enum" atribute from the input. + + +Suggestions for v1.39: + +* Add a boolean “bound” output to the various geometry property nodes, so materials can be flexible if a given attribute doesn’t exist. Especially ones like <texcoord> that don’t let users specify names. + diff --git a/documents/Specification/inprog_v1.39/media/MaterialX_1.39_Overview_v5.png b/documents/Specification/inprog_v1.39/media/MaterialX_1.39_Overview_v5.png new file mode 100644 index 0000000000..fd2cf1630f Binary files /dev/null and b/documents/Specification/inprog_v1.39/media/MaterialX_1.39_Overview_v5.png differ diff --git a/documents/Specification/inprog_v1.39/media/PBSdiagram.png b/documents/Specification/inprog_v1.39/media/PBSdiagram.png new file mode 100644 index 0000000000..f802e36615 Binary files /dev/null and b/documents/Specification/inprog_v1.39/media/PBSdiagram.png differ diff --git a/documents/Specification/inprog_v1.39/media/nodegraph1.png b/documents/Specification/inprog_v1.39/media/nodegraph1.png new file mode 100644 index 0000000000..56322249f4 Binary files /dev/null and b/documents/Specification/inprog_v1.39/media/nodegraph1.png differ diff --git a/documents/Specification/inprog_v1.39/media/nodegraph2.png b/documents/Specification/inprog_v1.39/media/nodegraph2.png new file mode 100644 index 0000000000..3611e93d3e Binary files /dev/null and b/documents/Specification/inprog_v1.39/media/nodegraph2.png differ