1

I want to load textures without callbacks like .onload(). I am trying to use texture from blob: https://plnkr.co/edit/n4CbWMEOAyJMQFYy

    const response = await fetch("./assets/texture.png");
    const imageBlob = await response.blob();
    const imageBitmap = await createImageBitmap(imageBlob);
    console.log(imageBitmap);

    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, imageBitmap);

Expected result is:

enter image description here

But I have this:

enter image description here

I can see in the Network tab that the image has been uploaded:

enter image description here

This line of code console.log(imageBitmap); says that the image exists:

enter image description here

texImage2D() documentation says that I can use ImageBitmap as source.

Updated

I tried to use the loadImage function from this answer: https://stackoverflow.com/a/52060802/4159530 Playground: https://plnkr.co/edit/n4CbWMEOAyJMQFYy

function loadImage(url) {
    return new Promise(resolve => {
        const image = new Image();
        image.addEventListener('load', () => {
            resolve(image);
        });
        image.src = url;
    });
}

/* ... */

async function init() {
/* ... */

    const image = await loadImage("./assets/texture.png");
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

/* ... */
}

But that didn't solve the problem.

8Observer8
  • 868
  • 10
  • 17
  • I haven't used the `response.blob()` mechanism, but I have had success using `Image()`. Can you take a look at https://stackoverflow.com/a/52060802/691711? Maybe the way the blob is formed is causing issues. I think `Image()` may also do the handling of the encoding but I might be making assumptions there. – zero298 Oct 31 '22 at 19:39
  • Unfortunately `loadImage()` doesn't work: `const image = await loadImage("./assets/texture.png");` – 8Observer8 Oct 31 '22 at 20:02
  • @zero298 I added to my post what I tried on your advice. – 8Observer8 Oct 31 '22 at 22:31
  • @zero298 You can try it on Playground: https://plnkr.co/edit/n4CbWMEOAyJMQFYy – 8Observer8 Oct 31 '22 at 22:43
  • @zero298 now it works! I added `draw();` after `gl.texImage2D`: https://plnkr.co/edit/n4CbWMEOAyJMQFYy But I don't understand why is this `draw()` function being skipped: ```function main() { if (!init()) return; draw(); }``` – 8Observer8 Nov 01 '22 at 09:35

2 Answers2

1

This answer helped me to solve the problem: https://stackoverflow.com/a/52060802/4159530

Playground: https://plnkr.co/edit/n4CbWMEOAyJMQFYy

function loadImage(url) {
    return new Promise(resolve => {
        const image = new Image();
        image.addEventListener("load", () => {
            resolve(image);
        });
        image.src = url;
    });
}

/* ... */

async function init() {
/* ... */

    const image = await loadImage("./assets/texture.png");
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    draw();

/* ... */
}

As you can see, I call the draw() function after the gl.texImage2D() function. I don't understand why this draw() function is skipped:

function main() {
    if (!init()) return;
    draw();
}

Added 7/27/2023. I use this code to load textures and shaders using Fetch API (async/await): https://plnkr.co/edit/KaDgu8R6NJxnDEbO?preview

load-texture.js

import { gl } from "./webgl-context.js";

export default function loadTexture(url, minType = gl.NEAREST, magType = gl.NEAREST) {
    return new Promise(resolve => {
        const image = new Image();
        image.onload = () => {
            const texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minType);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magType);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            resolve(texture);
        };
        image.src = url;
    });
}

index.js

async function init() {
    const texture = await loadTexture("./assets/textures/texture.png",
        gl.LINEAR, gl.LINEAR);
    gl.bindTexture(gl.TEXTURE_2D, texture);
}

init();
8Observer8
  • 868
  • 10
  • 17
-1

[enter image description here][1]Loading Imagebitmap in gl.texImage2D() method works only in webgl2. var gl = someCanvas.getContext("webgl2");

It is working for me. [1]: https://i.stack.imgur.com/vgGPz.png

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 30 '23 at 06:34