there is a textured cube in my scene, and it renders well untill i draw a quad, then cube tuxture is gone, here is the render flow:
// draw the texture cube
gl.render(scene, camera);
// draw a quad on screen (for checking purpose), this tex is different from the cube
drawQuad(tex);
fake code inside drawQuad:
setupVertexBuffer();
gl.activeTexture(...);
gl.bindTexture(...);
gl.drawArrays(...);
gl.bindTexture(null);
I guess the problem is gl.bindTexture will replace TEXTURE0 with null or other texture, so when render the textured cube, its texture will be missing or wrong (correct me if i am wrong) (shouldn't webgl re-bind texture for geometries everytime before rendering?)
so i tried to rebind texture to the textured cube like this right before render the scene:
cube.map.texture = cubeTexture;
gl.render(scene, camera);
but it won't work.
then i tried to backup old texture before bind new one in drawQuad like this:
const lastTex = gl.getParameter(gl.TEXTURE_BINDING_2D);
but lastTex is always undefined
, so it won't work either.
what's the best way to let them both work correctly?
It turns out that sometimes just looking at the doc. is not enough. After carefully checking the source code of THREE.JS, I found WebGLState, which is responsible for texture binding in THREE.JS, so if I directly modify the texture binding externally will definitely mess up this WebGLState, so we can do this:
const gl = renderer.getContext();
// rendering with webgl shaders blah
{
setupVertexBuffer(...);
gl.activeTexture(gl.TEXTURE0 + 0); // bind webgltexture tex0
gl.bindTexture(gl.TEXTURE_2D, tex0);
gl.activeTexture(gl.TEXTURE0 + 1); // bind webgltexture tex1
gl.bindTexture(gl.TEXTURE_2D, tex1);
gl.drawArrays(...);
gl.bindTexture(gl.TEXTURE_2D, null); // deactive slot 1
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, null); // deactive slot 0
}
// tell THREE.js that no textures are now bound to slot0 and slot1
renderer.state.bindTexture(gl.TEXTURE_2D, null, 0);
renderer.state.bindTexture(gl.TEXTURE_2D, null, 1);
// now let THREE.JS render its scene
renderer.render(scene, camera);
The key point here is to tell THREE.js.WebGLState that the texture binding has changed so it can manage the states correctly for its rendering.
renderer.state.bindTexture(gl.TEXTURE_2D, null, 0);
renderer.state.bindTexture(gl.TEXTURE_2D, null, 1);
done.