User:Tamas Bates/NetProto/WebGL/Notes
Safe Texture Loading
Loading and creating a new texture can cause problems if it's possible the texture might get used before it's ready. First of all, the images used in a texture may be downloaded after your page is finished loading, leaving you with an uninitialized texture if you start to render too early. But because the recommended process of creating a texture is to do so in the image's OnLoad event, you can still be left with an incomplete texture (missing mipmaps, for example) even after all the resources have been downloaded.
To avoid the extra headache of tracking the state of all your textures, create a 1x1 solid-color texture as a placeholder, then replace it with the real texture once it's ready. This can be done safely without needing to block your render loop until everything has been downloaded, and will allow your scene to render even if there's an error retrieving the resources for one or more textures (e.g. if you're pulling texture resources from another domain, the browser may block them as a security risk).
var texture;
function initTextures() {
// create a new texture
texture = gl.createTexture();
// bind to the new texture so it's affected by future texture calls
gl.bindTexture(gl.TEXTURE_2D, texture);
// create a 1x1 pixel texture. The Uint8Array contains the RGBA values for the texture
// A nice idea might be to use an average color from your intended texture
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([255,255,255,255])); // white
// release the texture
gl.bindTexture(gl.TEXTURE_2D, null);
// create a new Image to hold our texture data
var img= new Image();
// hook OnLoad to do the actual texture creation after the image is ready for use (this call is asynchronous and will happen "whenever")
img.onload = function() { handleTextureLoaded(img, texture); }
// retrieve the desired image
img.src = "some/url.jpg";
}
function handleTextureLoaded(img, tex) {
// bind to the target texture (must have already been created by gl.createTexture)
gl.bindTexture(gl.TEXTURE_2D, tex);
// create a new texture from the content of the image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
// set your filtering parameters. NOTE: if using mipmaps (as below), your image MUST have dimensions matching a power of 2! Use gl.NEAREST instead of gl.LINEAR for non-mipmapped textures.
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); // must be called before using the texture
// release the texture
gl.bindTexture(gl.TEXTURE_2D, null);
}