solidangle
@solidangle

So far in our exploration of MaterialX, we've shown a basic MaterialX material that binds inputs to a standard surface, including textures.

You are not limited to values or textures as inputs though. You can construct arbitrary expressions that are linked to surface inputs, and build materials procedurally. This is similar to systems like Unreal's Material Editor or Substance Designer.

This marble material is another one of the MaterialX samples and uses zero textures.


<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
  <nodegraph name="NG_marble1">
    <input name="base_color_1" type="color3" value="0.8, 0.8, 0.8" uiname="Color 1" uifolder="Marble Color" />
    <input name="base_color_2" type="color3" value="0.1, 0.1, 0.3" uiname="Color 2" uifolder="Marble Color" />
    <input name="noise_scale_1" type="float" value="6.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Scale 1" uifolder="Marble Noise" />
    <input name="noise_scale_2" type="float" value="4.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Scale 2" uifolder="Marble Noise" />
    <input name="noise_power" type="float" value="3.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Power" uifolder="Marble Noise" />
    <input name="noise_octaves" type="integer" value="3" uisoftmin="1" uisoftmax="8" uiname="Octaves" uifolder="Marble Noise" />
    <position name="obj_pos" type="vector3" />
    <dotproduct name="add_xyz" type="float">
      <input name="in1" type="vector3" nodename="obj_pos" />
      <input name="in2" type="vector3" value="1, 1, 1" />
    </dotproduct>
    <multiply name="scale_xyz" type="float">
      <input name="in1" type="float" nodename="add_xyz" />
      <input name="in2" type="float" interfacename="noise_scale_1" />
    </multiply>
    <multiply name="scale_pos" type="vector3">
      <input name="in1" type="vector3" nodename="obj_pos" />
      <input name="in2" type="float" interfacename="noise_scale_2" />
    </multiply>
    <fractal3d name="noise" type="float">
      <input name="octaves" type="integer" interfacename="noise_octaves"  />
      <input name="position" type="vector3" nodename="scale_pos" />
    </fractal3d>
    <multiply name="scale_noise" type="float">
      <input name="in1" type="float" nodename="noise" />
      <input name="in2" type="float" value="3.0" />
    </multiply>
    <add name="sum" type="float">
      <input name="in1" type="float" nodename="scale_xyz" />
      <input name="in2" type="float" nodename="scale_noise" />
    </add>
    <sin name="sin" type="float">
      <input name="in" type="float" nodename="sum" />
    </sin>
    <multiply name="scale" type="float">
      <input name="in1" type="float" nodename="sin" />
      <input name="in2" type="float" value="0.5" />
    </multiply>
    <add name="bias" type="float">
      <input name="in1" type="float" nodename="scale" />
      <input name="in2" type="float" value="0.5" />
    </add>
    <power name="power" type="float">
      <input name="in1" type="float" nodename="bias" />
      <input name="in2" type="float" interfacename="noise_power" />
    </power>
    <mix name="color_mix" type="color3">
      <input name="bg" type="color3" interfacename="base_color_1" />
      <input name="fg" type="color3" interfacename="base_color_2" />
      <input name="mix" type="float" nodename="power" />
    </mix>
    <output name="out" type="color3" nodename="color_mix" />
  </nodegraph>
  <standard_surface name="SR_marble1" type="surfaceshader">
    <input name="base" type="float" value="1" />
    <input name="base_color" type="color3" nodegraph="NG_marble1" output="out" />
    <input name="specular_roughness" type="float" value="0.1" />
    <input name="subsurface" type="float" value="0.4" />
    <input name="subsurface_color" type="color3" nodegraph="NG_marble1" output="out" />
  </standard_surface>
  <surfacematerial name="Marble_3D" type="material">
    <input name="surfaceshader" type="surfaceshader" nodename="SR_marble1" />
  </surfacematerial>
</materialx>

As with our other materials, we have a 'standard_surface' surface shader. This time we are connecting inputs on the surface shader to outputs from the node graph 'NG_marble1'. Node graphs are a collection of nodes that form an expression graph. They may have zero or more inputs, and one or more outputs.

MaterialX comes with a number of stock nodes for use in node graphs. These range from simple nodes like 'add' or 'subtract', but can include complex nodes such as 'fractal3d'. You can read in detail about each standard node type in the MaterialX specification. Each node can have zero or more inputs, and one or more outputs.

One node of note is the 'position' node. MaterialX supports geometric properties, allowing Materials to use geometric data from the underlying mesh. The default space for the position node is object space, but you can get geometric data in other spaces by using the 'space' attribute.

Next time, we'll have an overview of how MaterialX generates shader code for its materials.


You must log in to comment.