1

How to use an array of textures (which contain different images) in WebGL without initializing each texture separately? I want to display a cube and a pyramid (organized as an array), each with a different texture image. Here is a part of the code (to initialize the textures):

function handleTexture(texture) {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.Img);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.bindTexture(gl.TEXTURE_2D, null);
}

function initTextures() {
    for (i=0; i<2; i++) {
        tex[i] = gl.createTexture();
        tex[i].Img = new Image();
        tex[i].Img.onload = function() { handleTexture(tex[i]); }
        tex[i].Img.src = texImgs[i];   // The name of the image file
    }
}

The cube and pyramid are displayed in black color (no texture), and I get this error in the page:

Uncaught TypeError: Cannot read property 'Img' of undefined  // gl.texImage2D()
tex.(anonymous function).Img.onload                          // tex[i].Img.onload = ...

I don't have this error if I initialize the texture separately, not using an array, but tex1 and tex2. Any suggestion on how to do this using array?

1
  • You can check this for adding texture to canvas in WebGL Commented Mar 17, 2016 at 11:57

1 Answer 1

1

When you do:

tex[i] = gl.createTexture();

tex[i] becomes a type of WebGLTexture and you cannot attach new properties on that object as you did with .Img property. So slightly more correct version would be:

var tex = [], texImgs = ['pyra.jpg', 'cube.jpg'];

function handleTexture(myTexture) {
    myTexture.texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, myTexture.texture);

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, myTexture.image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.bindTexture(gl.TEXTURE_2D, null);
}

function initTextures() {
    for (var i=0; i<2; i++) {
        (function(index) {
            tex[index] = new Object();
            tex[index].texture = null;
            tex[index].image = new Image();
            tex[index].image.onload = function() { handleTexture(tex[index]); }
            tex[index].image.src = texImgs[index];   // The name of the image file
        })(i);
    }
}

Note that you create an object that has image and texture property separated.

Hope this helps you.

EDIT:

Closure messes the index of the tex.

Sign up to request clarification or add additional context in comments.

6 Comments

Tried this, but now the cube and pyramid are not displayed. Then have this error: Uncaught TypeError: Cannot set property 'Img' of undefined (in tex[i].Img = new Image()). Anyway, if I initialize the texture not using an array, but tex1 = gl.createTexture(), afterwards I still can set tex1.Img = new Image().
Edited answer, try creating tex[i] as new object, maybe that is the problem.
The cube and pyramid are displayed now, but still in black. Then there's this error: Uncaught TypeError: Cannot set property 'texture' of undefined (myTexture.texture = gl.createTexture()).
Edited. I totally forgot about closure that doesn't exist in for loop, and async call of the tex[i]. It literally was trying to call handleTexture on tex[3]. This now should work 100%. :]
Thanks! It's working now. Anyway, it seems that WebGL really hates array.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.