Visitar URL original
fix: Warn about texture channel mismatches in the glTF exporter by willeastcott · Pull Request #9851 · playcanvas/engine · GitHub
Skip to content

fix: Warn about texture channel mismatches in the glTF exporter - #9851

Open
willeastcott wants to merge 1 commit into
mainfrom
claude/wizardly-mclean-a6f489
Open

willeastcott wants to merge 1 commit into
mainfrom
claude/wizardly-mclean-a6f489

Conversation

@willeastcott

@willeastcott willeastcott commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Follows #9837, which made the glTF exporter honour the clearcoat and sheen gloss invert flags and warn when it exports their gloss maps as roughness textures.

glTF reads each texture from fixed channels: occlusion, clearcoat, iridescence and transmission from red, roughness from green, metalness from blue, and sheen roughness and specular strength from alpha. The exporter attached material maps to these textures without checking which channel the material samples. Apart from the diffuse transmission map, whose channel it has moved into alpha since #9558, it exports texels unchanged.

Several StandardMaterial maps default to the green channel: aoMapChannel, clearCoatMapChannel, iridescenceMapChannel, metalnessMapChannel, refractionMapChannel, sheenGlossMapChannel and specularityFactorMapChannel. Materials authored in the engine therefore exported these maps, without any warning, to textures that glTF reads from a different channel. The base glossMap was also dropped silently unless it was the same texture as the metalnessMap, and glTF then read roughness from the metalness map's green channel.

Materials imported from glTF set the channels glTF reads, so they export as before, with no warnings.

Changes

  • The exporter warns when a material samples a map from a different channel than the one glTF reads that texture from. This covers every texture slot it exports.
  • Maps exported as a channel copy, which feat: Support the KHR_materials_diffuse_transmission glTF extension #9558 added for the diffuse transmission map, don't trigger the warning, because the copy already holds the map in the channel glTF reads. The diffuse transmission color map isn't copied, so it is checked like the other color maps.
  • It warns when glossMap and metalnessMap aren't the same texture. In that case the gloss map isn't exported, and glTF reads roughness from the metalness map.
  • When glossMap and metalnessMap are the same texture, it checks glossMapChannel and glossInvert, as fix: Honour the clearcoat and sheen gloss invert flags in the glTF exporter #9837 does for the clearcoat and sheen gloss maps.
  • The GltfExporter#build documentation lists these limitations.

A grayscale texture holds the same data in its red, green and blue channels, so a warning such as aoMapChannel 'g' against glTF's 'r' is harmless for it. The exporter can't tell without reading the texels.

Public API

No API changes. build() can log new console.warn messages, and its documentation is updated.

Tests

  • Every texture slot that glTF reads from fixed channels exports without a warning when the material samples the map from the glTF channel, and with one warning otherwise.
  • Gloss and metalness maps in the same texture, in different textures, or only one of them.
  • A round trip that imports a glTF material using every one of these textures, then exports it with each texture in place and no warnings.

Verification

  • npm run lint: no errors.
  • npm test: 4566 passing, 43 pending.
  • npm run test:webgpu: 4564 passing, 40 pending.
  • npm run docs: no warnings, and the new links in the build() documentation resolve.
  • 20 of the new tests fail against the exporter on main: the 16 channel mismatch cases and the 4 gloss and metalness cases.

Possible follow-up

The channel copy added for the diffuse transmission map could also move the other single-channel maps into the channel glTF reads, so they export correctly instead of only producing a warning.

🤖 Generated with Claude Code

glTF reads each texture from fixed channels, such as occlusion,
clearcoat, iridescence and transmission from red, metalness from blue,
and sheen roughness and specular strength from alpha. Apart from the
diffuse transmission map, whose channel it moves into alpha, the
exporter attached material maps to these textures without checking
which channel the material samples, and exported their texels
unchanged. The StandardMaterial defaults for the AO, clearcoat,
iridescence, metalness, refraction, sheen gloss and specularity factor
maps are the green channel, so materials authored in the engine
exported these maps to textures that glTF reads from a different
channel. Materials imported from glTF set the channels glTF reads, so
they were unaffected.

glTF also reads roughness from the metallic-roughness texture, which the
exporter fills from the metalness map. A gloss map that wasn't the same
texture as the metalness map was dropped silently, and glTF read
roughness from whatever the metalness map held in its green channel.

The exporter now warns when a material samples a map from other
channels than glTF reads, when its gloss and metalness maps aren't the
same texture, and when its base gloss map holds gloss rather than
roughness, as it already does for the clearcoat and sheen gloss maps.
The build() documentation describes these limitations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2774.6 KB (+433 B, +0.02%) 719.3 KB (+133 B, +0.02%) 558.2 KB (+431 B, +0.08%)
playcanvas.min.mjs 2771.3 KB (+433 B, +0.02%) 718.2 KB (+140 B, +0.02%) 557.4 KB (+55 B, +0.01%)

This branch was successfully deployed

2 active deployments
Preview – engine — 730601ba Deployed Oct 28, 2026 by vercel[bot]
Preview – engine-api-docs — 730601ba Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant