Hi, thanks R0J0hound for your super helfpul answer.
Sadly I had already found a way to do this.
Indeed what I do right now, is I draw the letter on a black canvas the size of the letter, multiply by my color, and draw the letter again in 'destination-in' mode to mask the canvas's content.
Then to save performance, I cache the texture in an object and if I ever need to redraw that letter with that color, I don't need to redo the process. This is helpful given that in a game the colored parts of the text are often the same words.
But indeed this is problematic on WebGL because changing an image to a webGL texture had some issues. So I decided to cache the texture as well. So I draw the image, convert it to a texture only once.
However, this still has some overhead compared to the canvas reder mode.
I'll need to see if recoding the same process in WebGL will save more perf compared to keeping what I have right now or not.
Also I don't think breaking C2's batch is a good idea. I have little to no experience in WebGL so I'm probably wrong, but afaik this means that the rendering gets a lot more tedious the more I have letters since I need to create a new batch and break it for each letter. Also I wasn't able to create a new proper batch using the same params C2 uses because I can't access these values, but again, maybe it's due to my inexperience with WebGL
function getColoredTexture(inst, image, color, clip, scale, letter) {
if(!color || color === 'None') {
return image
}
if (inst.cachedImages !== undefined && inst.cachedImages[letter] !== undefined && inst.cachedImages[letter][color] !== undefined) {
return inst.cachedImages[letter][color];
}
// Create new canvas
var charCanvas = createCanvas(clip.w * scale, clip.h * scale)
var charContext = charCanvas.getContext("2d");
// Draw letter on it
charContext.fillStyle = 'black';
charContext.fillRect(0, 0, charCanvas.width, charCanvas.height);
charContext.drawImage(image,
clip.x, clip.y, clip.w, clip.h,
0, 0, clip.w * scale, clip.h * scale);
// Apply color
charContext.globalCompositeOperation = 'multiply';
charContext.fillStyle = color;
charContext.fillRect(0, 0, clip.w * scale, clip.h * scale);
// Restore the transparency
charContext.globalCompositeOperation = 'destination-in';
charContext.drawImage(image,
clip.x, clip.y, clip.w, clip.h,
0, 0, clip.w * scale, clip.h * scale);
// Restore composite operation
charContext.globalCompositeOperation = 'source-over';
if (inst.cachedImages === undefined) {
inst.cachedImages = {}
}
if (inst.cachedImages[letter] === undefined) {
inst.cachedImages[letter] = {}
}
inst.cachedImages[letter][color] = charCanvas
return charCanvas
}
Here's the code and here's how it looks
cdn.discordapp.com/attachments/183566321156358144/481403367705542659/2018-08-21_11-58-23.gif
EDIT: Just realized I should probably not recreate a whole new canvas each time. I'll change that.