Add an observable: "onErrorObservable" for textures

Hello,

Currently we can load a texture and check that it is valid with the observable: texture.onLoadObservable, but we cannot use an observable to check its loading failure.

Here is what I would like to be able to do:

setBoxTexture() {
    const textureUrl = prompt("URL texture :", "Assets/Textures/s05_stwl_s_01.png");
    
	const boxMaterial = new BABYLON.StandardMaterial("boxMaterial", this.scene);
    
    if (textureUrl) {
        const texture = new BABYLON.Texture(textureUrl, this.scene, false, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE, null, null, null, null);
        
        texture.onLoadObservable.add(() => {
            boxMaterial.diffuseTexture = texture; 
        });

        texture.onErrorObservable.add(() => {
            console.error("Error loading texture. Application of default color.");
            boxMaterial.diffuseColor = new BABYLON.Color3(0.07, 0, 0.8); 
        });

    } else {
        boxMaterial.diffuseColor = new BABYLON.Color3(0.07, 0, 0.8);
    }
    
    this.tempBox.material = boxMaterial;
}

Currently I did it using texture.isReady() like this:
(It’s the same function, but without the loading error observable.)

setBoxTexture() {
	const textureUrl = prompt("URL texture :", "Assets/Textures/s05_stwl_s_01.png");
	
	const boxMaterial = new BABYLON.StandardMaterial("boxMaterial", this.scene);
	
	if (textureUrl) {
		const texture = new BABYLON.Texture(textureUrl, this.scene, false, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
		
		texture.onLoadObservable.add(() => {

			if (texture.isReady()) {
				boxMaterial.diffuseTexture = texture; 
			} else {
				console.error("Error loading texture. Application of default color.");
				boxMaterial.diffuseColor = new BABYLON.Color3(0.07, 0, 0.8); // Couleur par défaut
			}
		});

	} else {
		boxMaterial.diffuseColor = new BABYLON.Color3(0.07, 0, 0.8); // Couleur par défaut
	}
	
	this.tempBox.material = boxMaterial; 
}

The question is would it be useful to add onErrorObservable to verify that the texture failed to load.

technically you are using the wrong function, you should not use isReady to check for loading error.

isReady can be false after a successful texture load for a few frames due to it still being set up internally ( creating mipmaps and whatever else ) then it becomes true.

The correct function to use is isReadyOrNotBlocking

code looks like this :

/**
     * Get if the texture is ready to be consumed (either it is ready or it is not blocking)
     * @returns true if ready, not blocking or if there was an error loading the texture
     */
    public isReadyOrNotBlocking(): boolean {
        return !this.isBlocking || this.isReady() || this.loadingError;
    }

The texture class does accept an error callback as one of the arguments :

* new Texture(url, sceneOrEngine?, noMipmapOrOptions?, invertY?, samplingMode?, onLoad?, onError?, buffer?, deleteBuffer?, format?, mimeType?, loaderOptions?, creationFlags?, forcedExtension?): [Texture](https://doc.babylonjs.com/typedoc/classes/BABYLON.Texture)

( I cant wait for the day these functions accept a single options argument haha ) anyway…

The Texture class does have a property getter named loadingError which you can use to know if an error occurred .( returns a boolean )

If you use the callback it will be passed an object with two properties , “message” and “exception”

3 Likes

In fact, it was in the case where the texture URL is bad, the texture does not load. So I wanted to display a color by default instead of a texture which fails.

But maybe my approach is not the right one. Hence my proposal to add a observable onError on a texture.

I suspected that isReady is not appropriate here, even though it seems to work.

if you can provide a PG that illustrates what you want I should be able to help (either with an observable or anything that could help)

Hi DK,

The PG works. I commented on what I would like to do with an onErrorObservable and another comment where I use isReady which is less appropriate.
I know there is also an onError in the BABYLON.Texture constructor that can do this. But I told myself that this could perhaps also be done with an observable like for texture.onLoadObservable

It’s just an idea I’m proposing. I did this intuitively, thinking that we could do it (onErrorObservable like onLoadObservable), and I saw that this observable did not exist.

  • If you enter a url in the dialog this assigns a texture.
  • If we leave a string empty, this assigns a color.
  • If the URL is bad, capture the error and display a color instead of the texture.
1 Like

Guess what it is somehow already supported:
Babylon.js Playground

The nuance is that because the error can happen in so many different places we had to put it on a static function for each endpoint to call it

2 Likes

It’s cool. So BABYLON.Texture.OnTextureLoadErrorObservable takes into account the texture being loaded?

And then to know which texture is the problem we do:

BABYLON.Texture.OnTextureLoadErrorObservable.add((data) => {
            console.log(data.url); 
});

Seems good to me.

Thanks Dk

1 Like