I'm new to WebGL (and 3D graphics in general) and am using three.js. What I want to do is create multiple textures from a 2D canvas, and use them to render multiple meshes, each with a different texture.
If I just pass the canvas to a new THREE.Texture() prototype, the texture will change to whatever the canvas currently is. So all my objects have the same texture. My solution was to store each canvas array using getImageData() and create a new texture by passing that data to a new THREE.DataTexture() prototype. However, chrome keeps throwing errors, and when I run it on firefox, the texture is displayed upside down.
userName = $nameInput.val();
ctx2d.fillText( userName, 256, 128);
var canvasData = ctx2d.getImageData(0,0,512,256);
texture = new THREE.DataTexture(canvasData.data, 512, 256, THREE.RGBAFormat);
texture.needsUpdate = true;
material = new THREE.MeshBasicMaterial({ map: texture });
geometry = new THREE.PlaneGeometry(20,10);
textMesh = new THREE.Mesh( geometry, material);
scene.add(textMesh);
Chrome and Safari log the following error: WebGL: INVALID_OPERATION: texImage2D: type UNSIGNED_BYTE but ArrayBufferView not Uint8Array. However firefox plays it, though the texture is upside down.
According to the Mozilla documentation, the data is a Uint8ClampedArray. So assuming this is the problem, I can get around the above error by creating a new Uint8Array() and passing the data to it, per below:
var data = new Uint8Array(canvasData.data);
texture = new THREE.DataTexture(data, 512, 256, THREE.RGBAFormat);
However its still displaying upside down. What's going on?
Three.js initializes lazily so theoretically you could init your textures by calling
renderer.render
You can also call
renderer.setTexture(texture, slot)
which works but is arguably the wrong thing to do as based on both the name, docs, and signature of the function there's no guarantee this will work in the future.As for flipping use
texture.flipY = true;