So this is a very common problem that every 3D engine deals with in its own way. The tl;dr is, there’s no easy answer across the board, but I added some examples using a library I made to combine a few techniques, but it’ll still require you to fine tune a bit because it’s not a silver bullet.
The long answer: transparency + blending is hard to get both correct and fast in all cases, so every 3D engine chooses some compromise. The reason for this is that lots of 3D engines deal with occlusion by recording the distance of the closest thing to the camera at every pixel; when you draw a new thing, if it’s going to be farther than that distance, it doesn’t get drawn. This breaks transparency because a semitransparent thing still ends up recording that distance, preventing anything else from drawing behind it. The solution is generally to draw in back-to-front order like you would in 2D mode, or often just draw the transparent things after all the opaque things (the compromise most games make.)
To make that easier, I made a little library to help. Just loading the library looks like this: type-load-google-fonts-webgl_a copy copy by davepagurek -p5.js Web Editor
It mooostly fixes the text that you draw before the semitransparent stuff. Not fully though; what it does here is it fully discards any completely transparent pixels. The semitransparent pixels around the antialiased edges are still a problem though, leaving a bit of a border.
With this library, anything with some (semi-)transparency that you draw, wrap it in drawTransparent(() => yourCodeHere())
and the library manages the depth sorting for you. But that also sorts each drawTransparent
call back-to-front for you. If you have a single object that partially intersects other things like your text does, you’ll likely have to split it up into multiple draw calls. In this case, each letter is maybe the best you can reasonably do. Even still, because your rectangles are so big, you’ll get some glitchy clipping on each letter because each rectangle will still partially go over and partially go under the letters. But at least with the library doing the back-to-front drawing for you, you can more safely disable depth testing. That looks like this: type-load-google-fonts-webgl_a copy copy copy by davepagurek -p5.js Web Editor
(edit: better screenshot)
In case you want to see what other options are available in the wild, there’s a technique called depth peeling that gets you correct transparency regardless of what order you draw in, but it involves a lot more memory (you store many layers of your image as you draw to it) and can end up affecting performance a lot. Another option is to only draw opaque pixels, so if you have a semitransparent one, you randomly assign it full transparency or discard it weighted to the amount of transparency. This also works but gives you a grainy result unless you draw at a larger resolution and then sample the result down, which also affects performance/memory in general.
Hopefully that helped, sorry for the wall of text! let me know if I can elaborate on anything!