Reputation:
In my WebGL program that I'm writing in ES6, I have a class called Texture.
At first, it draws the texture as 1 red pixel. Once the image loads, I want to replace the red pixel with an image.
I'm a bit stuck as I'm not sure what the best approach for this as it currently throws an error and doesn't work:
Uncaught TypeError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': No function was found that matched the signature provided.
My best guess is that this happens because JavaScript is asynchronous, so once the image loads, gl is gone, or maybe I'm wrong about this.
Help understanding this and/or a solution would be great appreciated.
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);
}
}
}
I did try this:
this.img.onload = function(gl) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}
But it throws this error:
Uncaught TypeError: t.texImage2D is not a function
Upvotes: 1
Views: 412
Reputation: 2153
Keyword this
inside your onload
function is not the same this
context you expect. One way is to use arrow function as in Sebastian Speitel's answer.
You can also save the reference into self
variable, which is a common pattern:
var self = this;
this.img.onload = function() {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.img);
}
Any function can access a variable from outer scope, that's why self
is accessible inside this.img.onload
.
Upvotes: 0
Reputation: 7346
You are creating a new scope inside the function. The easiest way to prevent it in ES6 is an arrow function:
this.img.onload = () => {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}
Upvotes: 1