ImageBitmapLoader during runtime: once with await async and once with callback

The ImageBitmapLoader is a very elegant loader. I can return its result directly from a worker to the main thread without having to put it in a blob. Since the ImageBitmapLoader should be very resource-efficient, I thought I would test it in the main thread and have built the following class method, which I call once in the render update.

   const loader = new THREE.ImageBitmapLoader()
			.load('./resources/textures/colormaps/metals/pattern2.jpg', function (image){
		 		const texture = new THREE.CanvasTexture(image);	
				this.material_.uniforms.colourMap.value = texture;
				this.material_.uniformsNeedUpdate = true;

The image is loaded, the texture is created. I checked that. But the transfer to the shader does not work other than via the worker. In the worker I load

const loader = new THREE.ImageBitmapLoader();
const texture = await loader.loadAsync(url);

and in the main thread I then do the render update once

this.material_.uniforms.colourMap.value = texture;
this.material_.uniformsNeedUpdate = true;

why does the worker variant work but not the one from the example that I use from the ImageBitmapLoader description with the callback although the console shows me that the image is loaded and the texture has been generated?

I think the following line needs to be changed accordingly…

this.material_.uniforms.colourMap.value = image

And the line above it deleted maybe? ImageBitmapLoader is already returning a texture yet you’re then going on to try to create a CanvasTexture from the result, that doesn’t seem right…

It doesn’t work without CanvasTexture. The documentation also says CanvasTexture, that’s where I got it from.

from three.js documentation

Without CanvasTexture it’s an imageBitmap object, with it’s a texture object. So they are really two different types of data. Nevertheless, I tested your suggestion with my working worker variant, because maybe it could have worked. However, without the preconditioning by CanvasTexture, the shader becomes black. That means CanvasTexture is necessary for the shader to really get a texture object.

hmmm, then i’m not sure why the following works in your worker…

const loader = new THREE.ImageBitmapLoader();
const texture = await loader.loadAsync(url);

you’re simply setting your texture to the result from ImageBitmapLoader… can you share a minimal live reproduction on codepen or codesandbox?

The entire code is very large. I would have to make a smaller example that only deals with this specific topic. my worker returns the result of the imageBitmaploader. In the mainthread I then also use the CanvasTexture to make it the texture just like in the callback variant.

if(this.texUpdate == 0 && this.texloader_.newColorMaps.length > 0){
   const texture = new THREE.CanvasTexture(this.texloader_.newColorMaps[0].data);
   this.material_.uniforms.colourMap.value = texture;
   this.material_.uniformsNeedUpdate = true;
   this.texUpdate = 1;

here to supplement how I do it with the worker variant. So exactly the same, I only load the worker variant in the side thread with await async and only give a return after it is loaded. according to my understanding, a callback does that too. It loaded and converted in the callback, I see that too. So the texture definitely exists. It’s not bad if the callback variant doesn’t work because my worker is working, but i like to understand things. I have to name texture in my worker image, not texture that’s cleaner because in the worker it’s just the ImageBitmap and no CanvasTexture yet.

it does yes, i’m not sure, i can’t reproduce the error you’re getting, can you modify the following pen to demonstrate your setup?

As mentioned, my actual app is very large. I will build this tonight as a small example and then present it

I hope a github repository is just as good. I still have to familiarize myself with codePen.

my github repository

In the render method you can choose between the worker variant and the main thread variant with callback function. In the mainthread variant, the texture is definitely created, I checked that. But then it doesn’t show up in the shader. The worker variant works perfectly. Workers can’t exchange dom elements and that’s why I think ImageBitmapLoader is great, because they don’t have this limitation. ImageBitmapLoader makes using workers to load textures at runtime very easy. Nevertheless, I would also like to have the mainthread version work

Have you seen my repository? I’m curious where my thinking mistake is