Skip to content

Materials

Sebastien DUMETZ edited this page Oct 20, 2026 · 2 revisions

Material approximations

Phong and PBR cannot be matched exactly. The conversion policy is intentionally explicit:

Phong-to-PBR mapping

Source glTF mapping
Kd Linear baseColorFactor; default [0.8, 0.8, 0.8]
map_Kd sRGB base-color texture, multiplied by Kd; image policy, URI escaped. Options: see below
Ns Approximate perceptual roughness (2 / (Ns + 2))^(1/4)
Ks KHR_materials_specular, interpreted approximately as normal-incidence reflectance
Ni KHR_materials_ior; default 1.5
Pm, Pr Explicit metalness/roughness overrides
Ke Linear emissive factor
d, Tr Alpha, with d taking precedence regardless of property order; alpha below 1 uses BLEND; a PNG map_Kd also selects BLEND when any of its pixels is less than fully opaque, through an alpha channel or tRNS
illum 0 KHR_materials_unlit
illum 1 Specular disabled
illum 4, 9 (glass) KHR_materials_transmission of 1 − d; alpha stays 1 and the material OPAQUE
illum 6, 7 (refraction) KHR_materials_transmission of the mean of Tf (or Kt); d still sets alpha

Specular response and viewer support

Metalness defaults to zero: a large or colored Ks alone does not establish that a surface is metallic. With IOR 1.5, Ks is represented by specularColorFactor = Ks / 0.04; other IOR values use their corresponding Fresnel reflectance. IOR 1 produces zero dielectric reflectance. This preserves the approximate specular color/intensity for extension-aware viewers without inventing metalness. Core-only viewers use the metallic-roughness fallback and will render different specular responses. These material extensions are listed in extensionsUsed, not required, since core-only viewers still render a close fallback.

Color space and source metadata

Material colors and opacity are clamped to [0,1], shininess to nonnegative values, and IOR must be at least 1. Effective Phong parameters are retained under each material's extras.sourcePhong. Scalar colors are treated as linear; exporters that wrote sRGB scalar colors need preprocessing. Ambient Ka is omitted because ambient illumination belongs to the viewer's lighting.

Opacity and transmission

An alpha channel alone does not make a texture transparent: baking and photogrammetry tools often write RGBA PNGs whose alpha is 255 everywhere, and blending them would cost sorting artefacts and a transparent render pass for nothing. PNG textures are therefore decoded row by row on a background thread during the geometry conversion, which limits scan memory to a row and lets the scan overlap geometry processing.

MTL and glTF both separate two kinds of transparency. d dissolves a surface "unlike a real transparent material", which is glTF's alpha as coverage, as in Blender, three.js and obj2gltf. Light passing through a surface, MTL's glass and refraction illumination models, is KHR_materials_transmission, listed in extensionsUsed only; viewers without it render those materials opaque. glTF tints transmitted light with the base color, so Tf's own color is not kept, and Tf under other models is ignored, since some exporters write Tf 1 1 1 on every material. Raw d and Tf values remain in extras.sourcePhong. A used material that ends up fully transparent (d 0, or Tr 1 without d) is kept as written but reported, since it is usually an exporter writing Tr as opacity.

VRML materials

VRML material defaults are preserved, including zero specular color, shininess 0.2, transparency and emissive color. VRML shininess is converted to an exponent using a scale of 128. solid FALSE becomes doubleSided.

Diffuse texture options

map_Kd options from the MTL spec are honoured where glTF can express them:

  • -s and -o scale and offset the texture coordinates. They become KHR_texture_transform, listed in extensionsRequired because a viewer without it would place the texture wrongly, sampling at s·uv + o as three.js and Blender do, with the offset converted for glTF's flipped V. The w component is ignored.
  • -clamp on becomes a CLAMP_TO_EDGE sampler. That is identical within the 0–1 range, but beyond it glTF stretches the edge texels where MTL leaves the bare material; glTF has no closer mode.
  • Non-default -mm and -t cannot be represented and are ignored with a warning. -blendu, -blendv, -cc, -texres, -boost, -bm and -imfchan do not affect a diffuse map and are skipped.
  • Any other option is an error, since its argument count, and so where the path starts, is unknown.

Unsupported properties and missing UVs

Unsupported MTL maps/properties warn explicitly. Missing textures and image formats that cannot be decoded (or require disabled conversion) are errors. Faces without UVs cannot sample a texture, and glTF forbids their primitive from referencing one, so they use a copy of their material without the texture, named <material>-untextured, as obj2gltf does; a warning counts them. Separate opacity/specular/bump maps are not baked into PBR textures. Both OBJ and VRML UVs have V flipped for glTF's texture convention.

References

Policy references: KHR_materials_specular, VRML lighting model.

Conversion · Documentation home

Clone this wiki locally