I've been experimenting with adding both color and an image to a Three.js Mesh after it's already been rendered on the canvas. From what I understand, if I use the same material with both color and a map, they will blend together and there's no way to prevent that. For example, if I have a white image and add a yellow color, the color will tint the image yellow:
let material = new THREE.MeshLambertMaterial({
map: canvasTexture,
color: 0xCECECE
});
To work around this issue, I'm attempting to apply two separate materials to the mesh. One for the color and one for the image:
let material0 = new THREE.MeshLambertMaterial({
color: 0xCECECE
});
let material1 = new THREE.MeshLambertMaterial({
map: canvasTexture
});
var materials = [material0, material1];
mesh.material = materials;
Currently, when I try to set the mesh material to the array of materials, the mesh appears blank as if it's not accepting the array as a parameter. Even though the Three.js documentation states that it accepts an array of materials
Another potential issue I foresee is the default white color that may be applied to the material with just an image, thereby hiding the color of the material underneath.
So, how can I apply both an image and a color to a mesh material without them blending together? Adding two materials seems overly complex to me and could be challenging to manage in the long run.
UPDATE I discovered that the issue was with the texture I was using, which was a canvas texture. I needed to set the fill style of the canvas used in the canvas texture to be opaque. Something like:
ctx.fillStyle = "rgba(255, 255, 255, 0)";
After making this change, I was able to successfully add multiple materials to the mesh. The material using the canvas texture as the map had to be set to transparent. I also had to set the map.minfilter to be THREE.LinearFilter. I'm not sure why, but at least it's now functioning as intended :)
let material0 = new THREE.MeshLambertMaterial({
color: 0xf2f2f2
});
let material1 = new THREE.MeshLambertMaterial({
map: canvasTexture,
transparent: true
});
material1.map.minFilter = THREE.LinearFilter;
var materials = [material1, material0];
mesh.geometry.clearGroups();
mesh.geometry.addGroup( 0, 48, 0 );
mesh.geometry.addGroup( 0, 48, 1 );
mesh.material = materials;
I hope this explanation can be helpful to someone else facing a similar challenge.