We have an application that exports .glb files and when I try to load them in three.js using GLTFLoader the model shows no textures and I get this warning THREE.GLTFLoader: Unknown extension "KHR_materials_pbrSpecularGlossiness"
. The model and textures load fine in https://github.khronos.org/glTF-Sample-Viewer-Release/ so the file is ok.
The extension seems to be deprecated from three.js (https://github.com/mrdoob/three.js/pull/24950) and the suggestion is to convert the .glb file using gltf-extensions or gltf.report and save the new .glb file - this isn't very practical in my case, is it possible to tweak something to display the model with textures in three.js?
The code is standard enough:
const loader = new GLTFLoader();
loader.load(uri, function loaded(gltf) {
const model = gltf.scene;
const newMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });
model.traverse((o) => {
if (o.isMesh) {
// not sure if it's relevant but if I don't .clone()
// it removes the child and traverse crashes
let mesh = o.clone();
// const nextMaterial = new THREE.MeshPhysicalMaterial();
// THREE.MeshStandardMaterial.prototype.copy.call(mesh.material, nextMaterial);
// mesh.material = nextMaterial;
// mesh.material.metalness = 0;
scene.add(mesh);
}
});
I have tried:
Thanks!!
Newer versions of three.js do not include spec/gloss PBR materials, which this model requires. So there's no quick workaround here, the model must be converted to metal/rough PBR materials. That's potentially slow (textures must be rewritten) so I'd do it offline if you can.
Option 1: UI conversion
Load the model into https://gltf.report/, accept the prompt to convert the material, and then export the result to a new file.
Option 2: Offline command-line conversion
npm install --global @gltf-transform/cli
gltf-transform metalrough input.glb output.glb
Option 3: Runtime conversion with JavaScript
If you need to do it at runtime, then:
import { WebIO } from '@gltf-transform/core';
import { KHRONOS_EXTENSIONS } from '@gltf-transform/extensions';
import { metalRough } from '@gltf-transform/functions';
// Load model in glTF Transform.
const io = new WebIO().registerExtensions(KHRONOS_EXTENSIONS);
const document = await io.read('path/to/model.glb');
// Convert materials.
await document.transform(metalRough());
// Write back to GLB.
const glb = await io.writeBinary(document);
// Load model in three.js.
const loader = new GLTFLoader();
loader.parse(glb.buffer, '', (gltf) => {
scene.add(gltf.scene);
// ...
});