WebGL. Можно ли передать gl в функцию img.onload?

В моей программе WebGL, которую я пишу на ES6, у меня есть класс с именем Texture.

Сначала он рисует текстуру как 1 красный пиксель. Как только изображение загрузится, я хочу заменить красный пиксель изображением.

Я немного застрял, так как не уверен, какой лучший подход для этого, поскольку в настоящее время он выдает ошибку и не работает:

Uncaught TypeError: не удалось выполнить «texImage2D» в «WebGLRenderingContext»: не найдена функция, соответствующая предоставленной подписи.

Я думаю, что это происходит из-за асинхронности JavaScript, поэтому, как только изображение загружается, gl исчезает, или, может быть, я ошибаюсь.

Помощь в понимании этого и / или решения будет принята с благодарностью.

export default class Texture {
    constructor(gl, src) {
        // create texture then bind it
        this.texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, this.texture);

        // texture settings for the texture
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

        // create it as a red pixel first so it can be quickly drawn then replaced with the actual image
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));

        // active the texture
        gl.activeTexture(gl.TEXTURE0);

        // load the image
        this.img = new Image();
        this.img.src = src;

        // replace the red pixel with the texture once it is loaded
        this.img.onload = function() {
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
        }
    }
}

Я пробовал это:

this.img.onload = function(gl) {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}

Но выдает эту ошибку:

Uncaught TypeError: t.texImage2D не является функцией


person Edward    schedule 06.04.2018    source источник
comment
это полезно? stackoverflow.com/questions/49187705/   -  person gman    schedule 07.04.2018
comment
@gman это на самом деле информативно, как это работает, спасибо!   -  person Edward    schedule 09.04.2018


Ответы (2)


Вы создаете новую область внутри функции. Самый простой способ предотвратить это в ES6 — это стрелочная функция:

this.img.onload = () => {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}
person Sebastian Speitel    schedule 06.04.2018
comment
Это идеально, я приму ваш ответ, когда смогу, и прочитаю функции стрелок. - person Edward; 06.04.2018

Ключевое слово this внутри вашей onload функции не соответствует ожидаемому this контексту. Один из способов — использовать функцию стрелки, как в ответе Sebastian Speitel.

Вы также можете сохранить ссылку в переменной self, что является распространенным шаблоном:

var self = this;
this.img.onload = function() {
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.img);
}

Любая функция может получить доступ к переменной из внешней области видимости, поэтому self доступна внутри this.img.onload.

person Tomasz Bubała    schedule 06.04.2018
comment
Я только что проверил это, и это также работает. Спасибо за объяснение, хотя функция стрелки является моим предпочтительным решением для этого, но определенно полезно знать эту информацию, поскольку я нахожусь в процессе изучения ES6. - person Edward; 06.04.2018
comment
Да, используйте ES6, если можете. Стрелочные функции не имеют собственных this. This привязан к контексту, в котором они созданы, что полезно во многих ситуациях, например, как у вас :) - person Tomasz Bubała; 06.04.2018