Accessing Embedded Textures from Loaded Model

Hello,

I’m trying to take the embedded textures from the default material the FBX loader makes and assign them to a custom material and shader I made. I got the shader to use images just fine (Works when loading an image with the imageloader) but I can’t seem to figure out how to grab the image that was loaded with the model.

I’ve tried saving the material.map from the original loaded material and applying it to the new map property of my material, but it is always giving an undefined value. My guess is because it has not loaded at time of trying to access, but I’m not sure. Any ideas? If I use the commented out MeshStandardMaterial bit it works fine.

Here is what I have for trying to access the embedded textures. I’ve tried various thing around this but I feel like I’m just being dumb and missing something else important:

model.traverse(function (object) {
    if (object.isMesh) {
        for (let i=0; i < object.material.length; i++){
            oldMat = object.material[i];
            console.log(oldMat);
            //object.material[i] = new THREE.MeshStandardMaterial({ map: oldMat.map});
            object.material[i] = new THREE.ShaderMaterial( {
                uniforms: uniforms,
						vertexShader: vertexShader(),
						fragmentShader: fragmentShader(),
                defines: defines,
					} );
            //uniforms.map = new THREE.TextureLoader().load(`../assets/565654248956887061.png`)
            object.material[i].uniforms.map.value = oldMat.map;
            object.material[i].needsUpdate = true;
        }
        object.castShadow = true;
        console.log(object);
        if (object.name.includes('Bunny') || object.name.includes('Bot') || object.name.includes('Top')) {
            object.visible = false;
        };
    }
});        

Try this :thinking:

model.traverse(function (object) {
    if (object.isMesh) {
          let materiallist = []
        for (let i=0; i < object.material.length; i++){
            oldMat = object.material[i];
            console.log(oldMat);
            //object.material[i] = new THREE.MeshStandardMaterial({ map: oldMat.map});
            let newMat = new THREE.ShaderMaterial( {
                uniforms: uniforms,
						vertexShader: vertexShader(),
						fragmentShader: fragmentShader(),
                defines: defines,
					} );
            //uniforms.map = new THREE.TextureLoader().load(`../assets/565654248956887061.png`)
            newMat.uniforms.map.value = oldMat.map;
            newMat.needsUpdate = true;
            materiallist.push(newMat)
        }
        object.castShadow = true;
        object.material = materiallist
        console.log(object);
        if (object.name.includes('Bunny') || object.name.includes('Bot') || object.name.includes('Top')) {
            object.visible = false;
        };
    }
})

Hello, thank you for the reply!

I tried this and sadly does not work. However, I’ve tracked down the issue a little more. It does technically seem to be working, it’s just that it copies over the texture before it had fully loaded the image from the model resulting in just a black null texture being applied. I think that’s what’s happening here.

Does this mean that shadermaterial is an asynchronous operation?