Why glTF to USDZ converters break your materials

The conversion usually succeeds. That is the problem — a converter that drops half your material graph still exits zero, and nothing tells you the glass just turned into plastic.

Last reviewed July 27, 2026

The mismatch is structural, not a bug

glTF 2.0 has a small metallic-roughness core plus a growing set of ratified extensions that add real physical behaviour: transmission, volume, clearcoat, sheen, iridescence, anisotropy, specular. USDZ material authoring targets `UsdPreviewSurface`, a deliberately modest shader with a fixed input list — diffuseColor, emissiveColor, metallic, roughness, opacity, opacityThreshold, ior, normal, occlusion, clearcoat, clearcoatRoughness, displacement.

The core maps cleanly. Base colour, metallic, roughness, normal, occlusion and emissive all have obvious counterparts, and a competent converter gets them right. Everything outside that core has nowhere to go, and the standard behaviour is to drop it silently.

What survives and what does not

glTF featureFate in USDZWhat the shopper sees
Core metallic-roughness PBRPreservedCorrect
KHR_materials_emissive_strengthClamped to plain emissiveLess glow
KHR_texture_transformUsually mapped to UsdTransform2dCorrect if the converter supports it
KHR_materials_transmissionNo equivalentRefractive glass turns opaque
KHR_materials_volumeNo equivalentThickness and absorption vanish
KHR_materials_clearcoatInputs exist, rarely wiredLoses the lacquer highlight
KHR_materials_sheenNo equivalentVelvet and fabric read as flat
KHR_materials_iridescenceNo equivalentLoses the colour shift
KHR_materials_anisotropyNo equivalentBrushed metal loses its grain
KHR_materials_specularPartial at bestReflectance drifts
KTX2 / WebP texturesMust be re-encodedDepends on the re-encode

Bake it, do not hope

The only reliable answer is to flatten the lossy features into the base PBR slots *before* conversion, so the USDZ shows an intentional approximation rather than an accidental one. Concretely: render or approximate what the material looks like under typical lighting, and write that into base colour, metallic, roughness and opacity.

  • Transmission → set an alpha-blended base colour with an opacity that reads as glass, and raise roughness slightly so the surface still catches light.
  • Volume → bake the absorption tint into base colour; there is nowhere else for it to live.
  • Sheen → lift base colour at grazing angles is impossible in a static bake, so bake the average sheen contribution into base colour and accept the loss.
  • Clearcoat → lower roughness and raise the specular response of the base layer to approximate the coat.
  • Iridescence / anisotropy → bake a representative view into base colour. These are view-dependent by definition; a static approximation is the honest ceiling.

Doing this deliberately also gives you something to review. A baked approximation you signed off on is a product decision; a silently dropped extension is a defect you find from a customer email.

The non-material things converters also get wrong

  1. Units. glTF is metres by definition. USD carries metersPerUnit as stage metadata. A converter that writes metersPerUnit = 0.01 while leaving the geometry in metres produces a model 100× off — Safari 27 shipped a fix for exactly this class of bug.
  2. Up axis. Both glTF and Quick Look are Y-up, but USD stages can be Z-up, and a converter that passes through a Z-up stage gives you a product lying on its side.
  3. Texture encodings. If your glTF uses KTX2 (KHR_texture_basisu) or WebP (EXT_texture_webp), those cannot go into a USDZ — the package format allows PNG, JPEG, EXR and AVIF, and Quick Look in practice wants 8-bit PNG or baseline JPEG. Something must re-encode them, and that step is where quality quietly changes.
  4. Alpha modes. glTF MASK maps to opacityThreshold, BLEND to opacity. Converters that collapse both to plain opacity turn cut-out foliage or perforated leather into a smear.
  5. Double-sided flags and winding. Single-sided geometry authored for a renderer that ignores backfaces shows holes in Quick Look.
  6. Packaging. Even a perfect stage fails if the archive is written with compression or misalignment — see USDZ not working in Quick Look.

How to verify a conversion

Do not compare the USDZ against your expectations; compare it against the source. The useful questions are mechanical: which extensions did the source declare, which of them are in the lossy set, does the resulting stage carry the same mesh and triangle counts, do the UsdPreviewSurface inputs match the glTF material values input-by-input, and did any texture change encoding along the way?

That last one — a per-input diff between the glTF material and the round-tripped UsdPreviewSurface — is the check that catches converter regressions nothing else does. And it comes with an honest caveat worth repeating: comparing structure is not the same as comparing renders. Apple ships no headless Quick Look renderer, so no tool can promise you pixel parity with a real device. Structural parity plus a device check on your top SKUs is the realistic standard.

If you are choosing a converter, the useful test is not whether it produces a file. It is whether it tells you what it threw away. Related reading: why your USDZ renders pink and Safari 27 `<model>` requirements.

Common questions

Why does my glass material look opaque after converting to USDZ?
Because KHR_materials_transmission has no equivalent in UsdPreviewSurface. The extension is dropped during conversion and the surface falls back to its base colour and opacity. Bake a glass-like appearance into base colour and opacity before converting.
Which glTF material extensions survive conversion to USDZ?
The metallic-roughness core survives: base colour, metallic, roughness, normal, occlusion and emissive. KHR_texture_transform usually maps to UsdTransform2d. Transmission, volume, sheen, iridescence and anisotropy have no counterpart, and clearcoat has inputs in UsdPreviewSurface that most converters do not wire up.
Can I use KTX2 or WebP textures in a USDZ?
No. The USDZ package specification permits PNG, JPEG, EXR and AVIF, and AR Quick Look in practice is most reliable with 8-bit truecolour PNG and baseline JPEG. KTX2 and WebP textures must be re-encoded during conversion.
My model is 100 times too big in AR. What happened?
Almost certainly a metersPerUnit mismatch. glTF is defined in metres; USD stages declare their own unit scale. If a centimetre-authored stage declares metersPerUnit incorrectly, the model renders 100× off. Safari 27 shipped a fix for this exact class of bug in the <model> element.
Check your file

Reading about it is slower than measuring it. Drop your .glb, .gltf, or .usdz in and get every blocker on this page checked against the real bytes — packaging, textures, geometry, AR parity — with the fix for each one.

Check your file free at /scorecardNo account needed to run a check.

Related

Sources