In video games only color is applied to help speed up the loading process. After textures are ready, they replace the current colors. Is there a way to do this in WebGL
? All the tutorials I've seen so far only show how to load in color or texture (not one after the other).
I'd guess that the buffer for each shape needs to be altered after its texture is fully loaded. I would assume this is keyed via an AJAX call that the texture is available, then applied via some kind of JavaScript function. Does WebGL
have a built in way of doing this without a complicated image loading process?
In most games that I've seen with the behavior you describe they'll typically start with either per-vertex coloring or a VERY low res texture and "blend up" to the full texture when it becomes available. That sort of smooth transition is tricky, but if all you want is a quick "pop" from one to the other it shouldn't be too much trouble.
The basic route I would take is to create a vertex buffer that has both texture coord and color information, as well as two different shaders. One shader will use the color information, the other will ignore it and use the texture instead. You would signal the mesh to start using the texture-based one as soon as the texture is ready.
As for detecting the image load, that's not hard at all and you don't even need AJAX for it:
var image = new Image();
image.addEventListener("load", function() {
// Image is done loading, push to texture
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
// Set up any other state needed, such as switching the shader for the mesh
}, true);
image.src = src;
I'm not sure how much more help I can give on this subject without posting really large code blocks, but if you're still struggling I can detail some of the other parts.
The approach I would take is as follows
loadTexture(url, initialColor) {
var tex = gl.createTexture();
// start with a single color.
gl.bindTexture(gl.TEXTURE_2D, tex);
var pixel = new Uint8Array(initialColor);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, pixel);
// start loading the image
var img = new Image();
img.onload = function() {
// when the image has loaded update the texture.
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.generateMipmap(gl.TEXTURE_2D);
}
img.src = url;
return tex;
}
// Load a tree texture, use brown until the texture loads.
var treeTexture = loadTexture("tree.png", [255, 200, 0, 255]);
// Load a water texture, use blue until it loads.
var waterTexture = loadTexture("water.jpg", [0, 0, 255, 255]);
This is how most of the samples on http://webglsamples.googlecode.com work although they all default to blue textures.
You could easily extend that idea to use a solid color, the load a low-res texture, then when that finishes load a high-res texture.
Note: the code above assumes you are loading power-of-2 textures. If not you'll need to setup your texture parameters correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With