-
Notifications
You must be signed in to change notification settings - Fork 2
How to use MaterialX shaders
Consider, for example, the following robot model.
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.
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.
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).
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.
For now, it at least works. Not interesting yet, but wait a moment.
Next, we should assign an image texture to this diffuse layer. Add an Image Color3 node and select the albedo texture.
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.
Next, convert it to Vector2 using a Convert Vector3 Vector2 node. Connect it to the Texture Coordinates port of the Image Color3 node.
And now the texture is visible.
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.
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.
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.
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.
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.
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.
Next, the normal map. Use an Image Vector3 node and connect the previously used UV coordinates.
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.
The simple shader is finished. Add a little environment light.