0

Im trying to objectify an approach to loading textures in webgl. I have an array of planets set up to which I set an name and other values. All my textures are called sun.jpg, mercury.jpg etc so when I contstruct the name string I can use Planets[i].name+".jpg" to get the name of the texture. The error I get is

Uncaught TypeError: Cannot read property 'image' of undefinedSpheredPlanetsGL.js:138 handleLoadedTextureSpheredPlanetsGL.js:179 TextureName.(anonymous function).image.onload

I set up the textureName array like this: (this array holds the individual variables that i reference later)

var TextureName = [];
    function setBufferName()
    {
        for(var i = 0; i < Planets.length; i++)
        {
            TextureName[i] = {name: Planets[i].name+"TextureName"};
        }
    }

Then I init the textures like this: (This should ensure that the "sunTextureName" should reference "sun.jpg" and so on for all the planets)

function initTexture() 
    {
        for(var i = 0; i < Planets.length; i++)
        {
            TextureName[i] = gl.createTexture();
            TextureName[i].image = new Image();
            TextureName[i].image.onload = function () 
            {
                handleLoadedTexture(TextureName[i]);
            }
            TextureName[i].image.src = Planets[i].name+".jpg";
        }
    }

The error then occurs here when "handleLoadedTexture(TextureName[i])" is called and im not sure why the function is this:

function handleLoadedTexture(texture) 
    {
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.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);
    }

To be clearer the error occurs on this line gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);. I dont know why because i pass in the variable and i should reference what is in the array.

Any help?

1 Answer 1

1

The problem is the scope of your counter variable. Your loop increments the counter variable and exits when its larger or equal to Planets.length. When your callback is executed the loop already finished and i is left at Planets.length.

You can use an IIFE(immediately invoked function expression) to create a scoped copy of i like so:

    for(var i = 0; i < Planets.length; i++)
    {
        TextureName[i] = gl.createTexture();
        TextureName[i].image = new Image();
        TextureName[i].image.onload = (function (index) {
            return function () { handleLoadedTexture(TextureName[index]) }
        })(i);
        TextureName[i].image.src = Planets[i].name+".jpg";
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much it fixed everything!

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.