Remove duplicate materials & textures

Hello. I have a scene where multiple GLTFs are dynamically loaded, each with various materials, some of which are shared between them. I initially tried removing only the duplicate textures, since I noticed that some GLTFs, even when using the same source for both emissive and albedo channels, create separate textures for each channel in Babylon.js. This approach seemed to work initially.

However, I later realized that some materials were also duplicated, so I tried applying the same approach to materials, but for some reason, it doesn’t work — the duplicate material isn’t removed as expected. Additionally, in some cases, the scene.ready trigger doesn’t seem to be invoked, causing the scene to hang in a loading state indefinitely.

Any suggestions would be greatly appreciated.

ps: I read about a potential approach where I could load one GLTF containing only the materials, and then load the other GLTFs without materials, assigning the materials afterward. Unfortunately, this doesn’t really apply in my case because I’m not sure exactly which materials will be used across the GLTFs being loaded. Out of a library of 100 materials, only about 10 might actually be used, so loading the entire library just for a subset would be inefficient.

You can check the console to see the logs.
Thank you again for your help!

A couple of useful threads:

2 Likes

Hey, found why the materials are not disposed

I think you don’t need to check if the material is ready before to dispose, or if you want ot check if it is ready you need to put a mesh as param else the function return false all the way.

line 107
About your second issue related scene.ready I have no idea :frowning:

1 Like

I have tackled this recently. There are at least 4 options I can think of:

  1. Intercept materials/textures on load
  2. Assign ids via gltf extras property
  3. Use material.name as id
  4. Reference counting

The advantage of 1 is that you do not instantiate materials/textures. But, as shown below, you might need to override a private method which is gonna get ugly.

Below is an example for 1. See the link for other overridable methods.

var defaultMaterialSingleton = null;
// See https://github.com/BabylonJS/Babylon.js/blob/master/packages/dev/loaders/src/glTF/2.0/glTFLoader.ts#L2151
export default function override(BABYLON) {
    const defaultCreateDefaultMaterial = BABYLON.GLTF2.GLTFLoader.prototype._createDefaultMaterial;
    BABYLON.GLTF2.GLTFLoader.prototype._createDefaultMaterial = function(name, babylonDrawMode) {
        if (typeof name === "string" && name.startsWith("__GLTFLoader._default")) {
            if (defaultMaterialSingleton === null) {
                this._babylonScene._blockEntityCollection = !!this._assetContainer;
                defaultMaterialSingleton = new BABYLON.BackgroundMaterial("GLTFEmptyMaterial"); //#todo is this the cheapest material possible?
                this._babylonScene._blockEntityCollection = false;
                defaultMaterialSingleton.fillMode = babylonDrawMode;
                defaultMaterialSingleton.freeze();
            }
            defaultMaterialSingleton._parentContainer = this._assetContainer;
            return defaultMaterialSingleton;
        }
        return defaultCreateDefaultMaterial.call(this, name, babylonDrawMode);
    };
}

For 2 beware that you cannot set extra properties on textures :frowning:

For 3, well it is a name not an id. Ensure that nothing touches it.

For 4, I mean whether a texture is used by any material and whether a material is used by any mesh. Works as long as you do not preload (and don’t assign) materials/textures for later use.

2 Likes

When one has control over asset and materials kit (ie all materials with the same name are the same) - this is the best option.

Should there be a built-in way to check isReady bypassing the mesh check? For material management it makes sense to have an option to do this.

I have no idea :frowning:

Hey, thank you all.
I uesd MarianG idea to partialy fix my function, but I’ll trry to use Joe idea as well and Intercept materials/textures on load.