News for hackers. Stuff that matters.
Re:WebGPU Fundamentals by vbezhenar on Saturday April 15, 2023 @08:23AM (#35579975)
How do I render text with GPU? Do I render text on texture with CPU and then send that texture to GPU? Do I vectorize it and draw millions of tiny triangles to approximate those vectors? It's interesting for me to explore WebGPU as a canvas for app development, but it's not obvious to me how to draw text and text is everywhere.
Re:WebGPU Fundamentals by itronitron on Saturday April 15, 2023 @08:54AM (#35580209)
Some people have been using signed distance fields (sdf) to define fonts on the GPU.
Re:WebGPU Fundamentals by pavlov on Saturday April 15, 2023 @09:01AM (#35580258)
Note that this approach is useless on its own if your app needs to render user-created text because nowadays everybody expects emojis to work and look roughly the same as on Apple’s platforms, which means detailed multi-colored layered vector shapes that SDF font renderers can’t handle.
Re:WebGPU Fundamentals by esperent on Saturday April 15, 2023 @09:28AM (#35580463)
The solution I've used for this, which was a bit tedious but not that hard to implement, was sprites for the icons/emojis and SDF for everything else. I'm sure there would be other solutions too, like layering. So it's not useless, you just need to get creative to overcome the limitations. Like everything else in 3D graphics.
Re:WebGPU Fundamentals by pavlov on Saturday April 15, 2023 @10:15AM (#35580816)
Yes, I agree — I did write “useless on its own” to highlight that you need to extend the SDF rendering model with a different one to handle actual user-generated text.
Re:WebGPU Fundamentals by unconed on Saturday April 15, 2023 @02:41PM (#35583346)
Use.GPU handles this just fine: it uses a subpixel SDF mask with a plain color image. You get crisp edges, just the interior is a bit blurry.
Re:WebGPU Fundamentals by jkcxn on Saturday April 15, 2023 @08:54AM (#35580213)
If you have a couple of different sizes of texts you can render out each character into a sprite map and render a quad per character which is probably the fastest and works for most 2D UIs. You can prerender ahead of time or have some runtime code that renders the characters with a given font using the 2D canvas api. You will need also need to store the characters sizes somewhere unless it’s a monospace font

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

Re:WebGPU Fundamentals by bhouston on Saturday April 15, 2023 @09:15AM (#35580353)
The easiest is just to use a html canvas element and draw text to it and then upload that as a texture map. This can handle kerning, ligatures, emojis, different fonts and languages. Writing your own font layout tool is horribly difficult and only do it if you must.
Re:WebGPU Fundamentals by raphlinus on Saturday April 15, 2023 @09:17AM (#35580369)
One of the most exciting features of WebGPU, especially over WebGL, is the ability to run compute shaders. That opens up an entire class of 2D vector graphics rendering techniques using compute shaders, including Vello. It's still in early stages, but the current code does include text rendering. There's a very rough demo at https://levien.com/vello-demo (the demo doesn't do variable fonts but the code can), and we'll be polishing that in time for Chrome M113 going stable.
Re:WebGPU Fundamentals by pjmlp on Saturday April 15, 2023 @10:08AM (#35580752)
Thanks to Google blocking WebGL compute shaders adoption.

We could have had them three years ago.

Re:WebGPU Fundamentals by fulafel on Saturday April 15, 2023 @10:20AM (#35580852)
There's a lot of literature about font rendering predating compute shaders too, compute shaders are not a functional prerequisite by any means.

Here's eg one case: https://github.com/astiopin/webgl_fonts

Re:WebGPU Fundamentals by pjmlp on Saturday April 15, 2023 @11:16AM (#35581370)
Yeah, that as well.

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.

Re:WebGPU Fundamentals by CSSer on Saturday April 15, 2023 @10:14AM (#35580809)
Interesting. Do you have any more context around this? It sounds uncharacteristic of Google to do so given their usual stance on browsers being all things to all people.
Re:WebGPU Fundamentals by pjmlp on Saturday April 15, 2023 @11:12AM (#35581329)
Re:WebGPU Fundamentals by kimown on Monday April 17, 2023 @02:00AM (#35597275)
Yes, I also don't understand why google abandon webgl compute shader, just because webgpu will have same, so they force developer using newer api.
Re:WebGPU Fundamentals by coffeeaddict1 on Saturday April 15, 2023 @08:33PM (#35586070)
Is it (will it be) possible to use Vello from C++ or is this firmly Rust only?
Re:WebGPU Fundamentals by raphlinus on Saturday April 15, 2023 @09:18PM (#35586363)
There are no active plans to do this, but it's all open source and there are tools such as cbindgen, so if there is sufficient interest there's a good chance it will happen.
Re:WebGPU Fundamentals by dist-epoch on Saturday April 15, 2023 @09:22AM (#35580410)
> Do I vectorize it and draw millions of tiny triangles to approximate those vectors

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.

Re:WebGPU Fundamentals by raphlinus on Saturday April 15, 2023 @09:31AM (#35580485)
This is true, but there is a lot more to the story. For one, WebGPU does not (yet) support mesh shaders, though it may later as an extension. For two, consider a glyph such as "o" that has two contours. Real triangulation generates a mesh that only generates triangles between the outer and inner contours, and mesh shaders aren't good at that. There are techniques compatible with mesh shaders (cover and stencil) that draw twice, incrementing and decrementing a winding number stored in the stencil buffer (see contrast renderer[1] for a clean modern implementation), but it does require nontrivial tracking on the CPU side, and can result in lots of draw calls to switch between the cover and stencil stages unless sophisticated batching is done. (The outer contour is drawn as a disc with winding number +1, and the inner contour is drawn as a smaller disc with winding number -1, so the inner part ends up as 0)

Compute shaders avoid all these problems and work on WebGPU 1.0 today.

[1]: https://github.com/Lichtso/contrast_renderer

Re:WebGPU Fundamentals by dist-epoch on Saturday April 15, 2023 @09:34AM (#35580507)
> Real triangulation generates a mesh that only generates triangles between the outer and inner contours, and mesh shaders aren't good at that.

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.

Re:WebGPU Fundamentals by raphlinus on Saturday April 15, 2023 @10:12AM (#35580783)
You might be able to do something along those lines, but I know of no font / vector 2D renderer that does so. There is a lot of literature[1] on this, so I suspect if doing things similar to subdivision surfaces were viable for font rendering, it would have been explored by now.

[1]: https://2d.graphics/book/gpu_rendering.html

Re:WebGPU Fundamentals by flohofwoe on Saturday April 15, 2023 @09:26AM (#35580446)
It depends on the quality and performance requirements, but you are basically on your own (e.g. the browser's integrated text rendering won't be of much help unfortunately - at least if performance matters). You need to bring your own font data and 'pre-rasterize' glyphs either on the CPU or GPU into a font cache texture, or render directly on the GPU using an approach like Slug or Pathfinder.

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.

Re:WebGPU Fundamentals by bobajeff on Saturday April 15, 2023 @10:56AM (#35581183)
You could convert the paths in a font file into a series of triangles using some vertices as a control points for quadratic bezier curves. Then some code for laying out the glyphs in a line. Much of this could be done on a shader I think.
Re:WebGPU Fundamentals by softfalcon on Saturday April 15, 2023 @11:17AM (#35581382)
Most web games use the dom as a layer over top of the 3D canvas and then use 3D to 2D projections to align the elements. This allows you to use regular HTML and CSS for a lot of text elements.

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.

Re:WebGPU Fundamentals by jesse__ on Saturday April 15, 2023 @01:04PM (#35582415)
From personal experience, if you're trying to make a game that cares about its frame rate, do not ever use the DOM for anything, ever. It routinely takes several frames to layout a single absolutely positioned element.

I recommend the second option. Rasterize your font with stb_truetype to a bitmap, and draw quads yourself

Re:WebGPU Fundamentals by depressedpanda on Saturday April 15, 2023 @02:35PM (#35583286)
I'm curious, isn't something like a HUD a perfect thing to render in a DOM overlay?

It shouldn't matter that much if it takes a few frames to layout and/or update your ammo count or whatever.

Re:WebGPU Fundamentals by jesse__ on Saturday April 15, 2023 @07:57PM (#35585868)
It wouldn't matter if the DOM layout engine ran on a separate thread, but it runs on the main thread, so it blocks your games update loop for a few frames every time you shoot, 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

Re:WebGPU Fundamentals by charcircuit on Saturday April 15, 2023 @03:41PM (#35583904)
This doesn't work for webxr.