three.jsgltf

THREE.GLTFLoader: Unknown extension "KHR_materials_pbrSpecularGlossiness


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!!


Solution

  • 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);
      // ...
    });