Transferable Pixel-Perfect Material Graphs for Blender & Three.js
How I built the MaterialX Fidelity Suite, then used it to drive pixel-perfect MaterialX support in both Three.js and Blender — including custom noise node implementations that finally close the gap between reference renders and open-source tools.
Ben Houston • May 1, 2026 • 4 min read
MaterialX is an open standard for rich material graphs, but support for it in key open-source 3D tools like Blender and Three.js is still incomplete. If you try to import a .mtlx file in Three.js or Blender, the result rarely matches the reference renderer. Many standard MaterialX nodes are simply not supported, and when the nodes are supported they often behave incorrectly, with color shifts, mismatched noise, and transforms based on incorrect coordinate space assumptions.
I wanted to fix this comprehensively. To do it, I had to build a visual regression suite, rewrite Three.js shaders, and build a MaterialX-to-Blender graph compiler. Here is how I closed the gap.
The Problem: You Can't Fix What You Can't Measure#
Inspired by the Khronos glTF Render Fidelity suite, I built the MaterialX Fidelity Suite. It systematically renders and compares hundreds of MaterialX node configurations (math, logic, compositing, procedural noises, and surfaces) against the official materialxview reference renderer.
A sibling project to the MaterialX Fidelity Suite is the MaterialX Samples Library, which I created as the set of materials to test against. During the process of creating pixel-perfect MaterialX support for Blender and Three.js, I've expanded this set of samples pretty extensively. The majority of the samples are not complex materials, but rather simple materials that isolate specific nodes and parameters so that if there are mismatches between renders, it is pretty clear where the issue lies.
Three.js#
Three.js already had a MaterialX loader, built on TSL, but it was rough: it worked, but barely. Using the fidelity suite, I found dozens of issues:
mx_ifgreaterandmx_ifequallogic nodes were inverted.rotate2d,rotate3d, andplace2dhad to be rewritten to match reference matrix math.- boolean logic nodes didn't work with both floats and booleans as MaterialX expects.
But the biggest issue was procedural noise. Hash functions, octave accumulation, and parameter mappings in Three.js were "similar" to MaterialX, but similar isn't identical. A slightly different hash produces a completely different pattern. I ended up porting the exact MaterialX noise implementations into Three.js GLSL.
I also ran into the issue that MaterialX assumes a UV space that is upside down compared to Three.js, and its XYZ coordinate system is different as well. To get pixel-perfect results, I had to add conversions between MaterialX and Three.js coordinate spaces at the appropriate places.
The result is near-perfect reproducibility across nearly all 400+ samples. (See Three.js PR #33485)
Blender#
Fixing Blender was harder.
I started by writing blender-materialx-importer, a Python compiler that reads .mtlx files and generates equivalent Blender node networks. For example, a single MaterialX place2d node compiles down to a complex chain of Blender math and vector nodes just to get the coordinate spaces to match.
But Python wasn't enough. Just like in Three.js, Blender's native noise nodes couldn't match MaterialX's specific hash functions and domain transformations.
To fix this, I implemented pixel-perfect MaterialX noise functions directly in Cycles and Eevee and submitted them to Blender core: Blender PR #158054.
The Python importer is smart enough to use these native nodes if you're running the patched Blender build, falling back to rough approximations (with warnings) on vanilla Blender.
Try It Out#
We now have tooling that actually delivers on MaterialX's promise of write-once, render-anywhere materials:
- Three.js: Drop in a
.mtlxor.mtlx.zipfor a 1:1 real-time render. - Blender: Import any MaterialX material and get a perfectly matched Cycles graph (if you use the custom Blender from Blender PR #158054.)
- Other Renderers: Use the MaterialX Fidelity Suite to benchmark your own implementation.
This work is sponsored by Land of Assets.