MaterialX Needs a Single-File Container
MaterialX assets are multiple loose files, which breaks down in online, and collaborative contexts. The community has already solved this with zip packaging. We just need to formalize it as .mtlz.
Ben Houston • April 24, 2026 • 8 min read
At Land of Assets, we standardize on MaterialX and OpenPBR for material interchange.
That works well inside our pipeline. In collaborative and online delivery contexts, we ran into a practical gap: how do we exchange MaterialX materials between users and tools?
The Problem#
A typical MaterialX asset is a .mtlx file alongside multiple texture files, all wired together by relative paths that break the moment anything is moved or renamed. That structure is fine in a local DCC project folder. It is painful everywhere else:
- No single file to upload, version, or share
- Broken relative paths after moves or renames
- Multi-file uploads break CDN and API workflows.
For marketplace distribution and API delivery, you need one file per material.
The Community Already Solved This#
Poly Haven and the AMD Material Library (two of the most widely used public MaterialX repositories) both distribute materials as .mtlx.zip archives. This has driven real-world convergence on a consistent internal layout:

- One
.mtlxfile at the root of the archive, named after the material - All textures under
/textures/ - Other resources (node definitions, includes) in subdirectories
Keeping the root clear of everything except the primary .mtlx file makes the layout unambiguous. Any tool can identify the entry point without guessing.
Poly Haven and AMD converged on this layout through practice, not a committee decision.
The Missing Piece: A Dedicated Extension#
The one thing .mtlx.zip cannot provide is first-class recognition. Every operating system and browser sees it as a generic zip file, because it is one. There is no way to register a MIME type for it, no way to associate it with a material viewer, and no way for an API or CDN to distinguish a material package from any other archive.
A dedicated extension fixes all of that at no cost to the format itself.
The .mtlz Format#
.mtlz is a name and a spec for the layout Poly Haven and AMD already ship. The format itself is a standard zip archive.
Layout#
marble-cliff.mtlz
├── marble-cliff.mtlx ← exactly one .mtlx file, at the root
└── textures/
├── marble_cliff_diff.jpg
├── marble_cliff_nor_gl.exr
├── marble_cliff_rough.exr
└── marble_cliff_disp.png
Normative rules#
- The archive is a valid zip file.
- Exactly one
.mtlxfile appears at the root level. Its name can be anything, but this name may be used in UIs for the material's name, so it is best to name it something meaningful, rather than "material.mtlx". - All texture files are stored under subdirectories, such as
/textures/. - All other referenced resources (node definitions, includes, etc.) are stored in subdirectories, never at the root.
- The file extension is
.mtlz. - The MIME type is
model/materialx+zip.
The model/materialx+zip MIME type follows the structured syntax convention used across the web (the same +zip suffix pattern seen in model/vnd.usdz+zip) and extends naturally from the existing model/materialx type registered for .mtlx files.
Metadata#
MaterialX has no built-in fields for author, license, or provenance on the root <materialx> element. The format's <attributedef> mechanism, designed for standardized extensions, fills that gap cleanly: declarations are self-describing, and tools that do not understand them will, per the MaterialX spec, preserve and re-emit them unchanged.
We propose the following metadata fields as part of the .mtlz convention, using the materialx_ prefix to avoid collisions with other tools' custom attributes:
<?xml version="1.0"?> <materialx version="1.39" colorspace="lin_rec709" materialx_name="Marble Cliff" materialx_authors="Ben Houston ([email protected]), jcaron" materialx_license="CC0-1.0" materialx_license_url="https://creativecommons.org/publicdomain/zero/1.0/" materialx_source_url="https://example.com/materials/marble-cliff" materialx_version="1.0.0" materialx_description="A weathered marble cliff face with natural veining and displacement." materialx_keywords="marble, cliff, rock, natural, displacement, tiled"> <attributedef name="materialx_name" attrname="materialx_name" type="string" value="" elements="materialx"/> <attributedef name="materialx_authors" attrname="materialx_authors" type="string" value="" elements="materialx"/> <attributedef name="materialx_license" attrname="materialx_license" type="string" value="" elements="materialx"/> <attributedef name="materialx_license_url" attrname="materialx_license_url" type="string" value="" elements="materialx"/> <attributedef name="materialx_source_url" attrname="materialx_source_url" type="string" value="" elements="materialx"/> <attributedef name="materialx_version" attrname="materialx_version" type="string" value="" elements="materialx"/> <attributedef name="materialx_description" attrname="materialx_description" type="string" value="" elements="materialx"/> <attributedef name="materialx_keywords" attrname="materialx_keywords" type="string" value="" elements="materialx"/> <!-- material graph ... --> </materialx>
| Field | Format | Notes |
|---|---|---|
materialx_name | string | Human-readable material name |
materialx_authors | Name (email), Name | Comma-separated; email optional per author |
materialx_license | SPDX identifier | e.g. CC0-1.0, CC-BY-4.0, MIT; free string also accepted |
materialx_license_url | URL | Link to full license text |
materialx_source_url | URL | Canonical origin of this material |
materialx_version | SemVer | e.g. 1.0.0, 2.1.3 |
materialx_description | string | Free-text description of the material |
materialx_keywords | comma-separated strings | Search and discovery tags |
All metadata fields are optional in the draft spec. Some material library systems may require a subset for indexing, moderation, or discovery.
Zip format recommendations#
For streaming renderers, we recommend the following:
- File ordering: The root
.mtlxfile should be placed first in the archive, followed by other text files, and lastly the image files. Applications can then start parsing the material definition while textures are still loading. - Uncompressed storage: The files within the zip archive should be stored uncompressed. Renderers can memory-map the archive without decompressing it, giving direct access to image data.
What formalizing .mtlz enables#
With loose .mtlx.zip convention | With formalized .mtlz format |
|---|---|
| OS treats it as a generic archive | OS can associate it with a material viewer |
| No MIME type for routing | model/materialx+zip for APIs and CDNs |
| Browser offers generic zip handling | Browser can trigger material-specific handling |
| Ambiguous in material libraries | Unambiguous: this file is a material |
| Package structure is a loose convention | A formal spec defines valid structure and enables validation |
No metadata standard exists for .mtlx.zip | Metadata fields are standardized for indexing and provenance |
| Library and pipeline automation is heuristic-based | Automation becomes reliable across search, policy, and workflows |
FAQ#
Why not just use a degenerate USDZ, glB, or Blend file?#
While USDZ, glTF (GLB), and Blender files can theoretically act as a container for materials, each introduces unnecessary complications:
- Ambiguous intent: It isn't clear from the file extension alone that it is a material-only file. So it has to be read and inspected to determine this.
- Validation overhead: These formats support many different variations of materials already. You would need to parse the file, validate that it contains only a material, and then validate that the material is fully compatible with the MaterialX specification.
- Translation complexities: These formats do not represent MaterialX directly. USDZ expects a USD Shade network, GLB translates materials to a JSON format (which has significant limitations compared to MaterialX), and Blender translates them to a Blender Shader Graph. Relying on these formats means you carry the heavy expectation of translating complex graph-based material definitions back and forth.
MaterialX has already emerged as the standard for graph-based materials with a well-defined file format. Adding a single-file container to that format is much easier than adopting a completely different file format, with all its associated complexities, just to get a zip container.
Path Forward#
At Land of Assets, we are testing the draft .mtlz format alongside our existing .mtlx.zip workflow in a real production scenario. This includes related tools and experiments in the same ecosystem, such as material-viewer.ben3d.ca and material-fidelity.ben3d.ca.
This is experimental. We welcome feedback and discussion from Poly Haven, AMD, and the broader MaterialX community. The format is already close to what everyone ships. The goal is a shared name, layout, and metadata spec.
If you are building material repositories, content pipelines, or DCC integrations, reach out.