MaterialX Needs a Single-File Container

7 min read Original article ↗

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:

MaterialX zip layout from PolyHaven and AMD Material Library

  • One .mtlx file 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#

  1. The archive is a valid zip file.
  2. Exactly one .mtlx file 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".
  3. All texture files are stored under subdirectories, such as /textures/.
  4. All other referenced resources (node definitions, includes, etc.) are stored in subdirectories, never at the root.
  5. The file extension is .mtlz.
  6. 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>
FieldFormatNotes
materialx_namestringHuman-readable material name
materialx_authorsName (email), NameComma-separated; email optional per author
materialx_licenseSPDX identifiere.g. CC0-1.0, CC-BY-4.0, MIT; free string also accepted
materialx_license_urlURLLink to full license text
materialx_source_urlURLCanonical origin of this material
materialx_versionSemVere.g. 1.0.0, 2.1.3
materialx_descriptionstringFree-text description of the material
materialx_keywordscomma-separated stringsSearch 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 .mtlx file 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 conventionWith formalized .mtlz format
OS treats it as a generic archiveOS can associate it with a material viewer
No MIME type for routingmodel/materialx+zip for APIs and CDNs
Browser offers generic zip handlingBrowser can trigger material-specific handling
Ambiguous in material librariesUnambiguous: this file is a material
Package structure is a loose conventionA formal spec defines valid structure and enables validation
No metadata standard exists for .mtlx.zipMetadata fields are standardized for indexing and provenance
Library and pipeline automation is heuristic-basedAutomation 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.