At Land of Assets, one of the pillars of our pipeline is standardizing on MaterialX and OpenPBR for material interchange.
That decision has been great for our pipeline. But in collaborative, sharing and online delivery contexts, it exposes a practical gap: how do we easily exchange a MaterialX materials between useres 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, download, version, or hash
- Broken relative paths after moves or renames
- Complex multi-file APIs and brittle CDN behavior.
For real collaboration, marketplace distribution, and API-driven delivery, you need one file per material.
Poly Haven and the AMD Material Library — two of the most widely used public MaterialX repositories — both distribute materials as .mtlx.zip archives. This works well, and it 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 is what makes the layout unambiguous — any tool can identify the entry point without guessing.
This convention did not emerge from a committee. It emerged from practice. The demand is clear and the solution is already proven.
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. 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 standard zip archive following the conventions already established by Poly Haven and AMD. We are not inventing a new format — we are naming and formalizing what the community built organically.
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 exactly 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 |
In the draft .mtlz spec, all of these metadata fields are optional. A valid .mtlz package can omit them entirely. That said, we expect some material library systems may choose to require some subset of these fields for indexing, moderation, provenance, or discovery workflows.
Zip format recommendations#
For optimal performance in modern streaming and rendering contexts, we recommend the following zip formatting practices:
- File ordering: The root
.mtlxfile should be placed first in the archive, followed by other text files, and lastly the image files. This ordering enables applications to read the material definition first in a streaming context and begin processing while the heavier textures are still downloading. - Uncompressed storage: The files within the zip archive should be stored uncompressed. This allows the archive to be memory-mapped directly by renderers, providing easy access to the image data without requiring additional transforms or uncompression on each access.
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, doing so introduces several 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 experimentally adopting the draft .mtlz format in parallel with our existing .mtlx.zip community-standard workflow to evaluate how well it performs 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 explicitly experimental, and we welcome feedback, critiques, and discussion from Poly Haven, AMD, and the broader MaterialX community to help push this initiative forward. The format is already close to what everyone is shipping — this effort is about aligning on a name, a layout, and a metadata convention.
If you are building material repositories, content pipelines, or DCC integrations and this resonates, we would love to hear from you.