Skip to content

How to use MaterialX shaders

Tugcga edited this page Aug 16, 2026 · 2 revisions

Consider, for example, the following robot model.

image_001

This is a model from some game assets (from which game?). While MaterialX contains several universal uber-shaders (Standard Surface, Open PBR Surface, GLTF PBR, USD Preview Surface, Disney Principled), we will recreate a simple shader from scratch and use textures from the game.

Before we start, there are some preparatory steps. First, switch the shading model to OSL. This is because MaterialX shader nodes are translated into OSL shaders, and Cycles actually renders this OSL shader.

image_002

Second, you need the add‑on MaterialXSI. It contains all built‑in MaterialX nodes, all of which have the prefix MX.

Okay, we are ready to construct the shader tree. This tree should use only MaterialX nodes; no other nodes are allowed. This is because, to convert the shader tree into an OSL shader, it uses built‑in MaterialX functionality. So, it only understands what it understands - nothing more.

Start by adding a Surfacematerial node. It is the root node where the MaterialX shader begins. Connect it to the material port of the root material node. Do not delete the DiffuseBSDF node. It will be used as a fallback if something goes wrong and MaterialX fails to compile the OSL shader.

image_003

The shader may start either from this Surfacematerial node or from Lama Surface. But Lama Surface is part of the special Lama family of nodes; we will skip it for simplicity.

Next, add a Surface node and connect it to the Surfaceshader port. This node gathers different aspects of the surface shader: how the surface looks (BSDF), how it illuminates the light (EDF), and transparency (Opacity).

image_004

Next, define the main diffuse layer of the shader. Add an Oren Nayar Diffuse BSDF node and connect it to the BSDF port of the Surface node.

image_005

For now, it at least works. Not interesting yet, but wait a moment.

image_006

Next, we should assign an image texture to this diffuse layer. Add an Image Color3 node and select the albedo texture.

image_007

But before it works, we should define UV coordinates. And here we run into a terminology problem. In MaterialX, there is a Textcoord Vector2 node, which gets the required UV channel. But it works for non‑OSL shaders. In OSL, the u and v channels are not texture coordinates; they are the barycentric coordinates of each triangle. So, for OSL, we need another approach.

We can get UV coordinates by using geometry properties. So, add a Geompropvalue Vector3 node and define the property name geom:uv. We need the Vector3 version instead of Vector2, because in Cycles, UV coordinates are stored in this form.

image_008

Next, convert it to Vector2 using a Convert Vector3 Vector2 node. Connect it to the Texture Coordinates port of the Image Color3 node.

image_009

And now the texture is visible.

image_011

For this game model, there is an additional mix texture with roughness, metallic, and ambient occlusion packed into channels. We will multiply the diffuse color by the ambient occlusion. So, add the texture.

image_011

Split the color into channels using a Separate3 Color3 node, then convert the B‑channel (which contains AO) into color using a Convert Float Color3 node, multiply this color by the diffuse color using a Multiply Color3 node, and finally connect the result to the Color port of the diffuse node.

image_012

Next, the metallic layer. Add a Conductor BSDF node. The metal color is defined by setting two values: IOR and Extinction. There is a special node that converts the color to these technical values. Use Artistic IOR, and connect the diffuse color to both the Reflectivity and Edge Color ports. Then pass the output ports to the conductor node.

image_014

To mix the diffuse layer with the metallic layer, add a Mix BSDF node, connect the metallic output to Fg, the diffuse output to Bg, and the G‑color of the mask texture to Mix. Finally, connect this mix node to the Surface input.

image_015

Next, roughness. It is stored in the R‑channel of the mask texture. But before it can be used, it requires some mathematical mapping. In fact, we will apply the formula (1 - v) * 0.5, where v is the R‑channel of the texture. Add a Subtract Float node, set the first port value to 1.0, and connect the R‑channel to the second port. Then add a Multiply Float node, connect the first port to the previous value, and set the second port value to 0.5.

image_016

The Roughness port in the conductor node is of type Vector2. So, convert our float value using a Convert Float Vector2 node and connect the result to the Roughness port.

image_017

Next, the normal map. Use an Image Vector3 node and connect the previously used UV coordinates.

image_018

Add a Normalmap Float node and connect the Vector3 output from the image node to the In port of this node. Then connect the Out port of the normalmap node to both Normal ports of the conductor and diffuse nodes.

image_019

The simple shader is finished. Add a little environment light.

tutorial_use_mx_Default_Pass_Main 1

Clone this wiki locally