We could have had them three years ago.
Here's eg one case: https://github.com/astiopin/webgl_fonts
WebGL 2.0 is kind of PlayStation 3 like in capabilities, that we seldom see that in action besides shadertoy, Google Maps/Earth, and 360° views on ecommerce sites is another matter.
https://registry.khronos.org/webgl/specs/latest/2.0-compute/
https://github.com/9ballsyndrome/WebGL_Compute_shader
And then Google decides not implementating it after all, because of WebGPU.
https://github.com/9ballsyndrome/WebGL_Compute_shader/issues...
Also, you can render and rasterize fonts + dynamic text to a texture and UV map it to a quad in 3D space if you need to. This is pretty inexpensive and easy to do as well.
Lastly, the most difficult but performant option is using a shader to compute the font rendering. This is basically moving the font raster from CPU to GPU and there are various shader examples for this in GLSL (popular shader format used by WebGL/OpenGL) that you can use.
I recommend the second option. Rasterize your font with stb_truetype to a bitmap, and draw quads yourself
It shouldn't matter that much if it takes a few frames to layout and/or update your ammo count or whatever.
Now, that's not to say it has to be that way; real engines have a separate render thread that would sort of solve that problem. And they run the game update code in parallel, and all kinds of other stuff. But, by the time you have all that stuff, you can probably rasterize a font and draw quads ;)
But don't take my word for it. Maybe it's better now. Make a thing that moves some divs around in a requestAnimationFrame callback and take a look at the profile. I bet 2% of the time the layout engine takes 30ms+ to do basically nothing
If you need to scale the text arbitrarily or render it in 3D space you can look at multi channel signed distance fields (MSDF) which also renders out each character but encodes some extra data which makes them scalable. It has pretty good results
Of course there's also always the option to overlay DOM elements over the WebGPU canvas if you just want to render some 2D UI on top of the 3D rendering.
That is becoming feasible, using something called mesh shaders. The millions of tiny triangles will only be created on the fly inside the GPU, you will just send the vector geometry.
Compute shaders avoid all these problems and work on WebGPU 1.0 today.
I'm a bit confused. Can't you send the shape of O as a low res rough band (a closed wide loop) and enhance it in the mesh shader? This is how previous generation tessellation shaders and sub-division surfaces worked.