notebook

a study in wgpu UI rendering

I have a serious problem with yak shaving. I like understanding things and the best way for me to understand things is by learning how they work and how to make it for myself. So, in my quest to make a CAD program that I don't actively hate, I'm shaving a lot of yaks.

One pretty major yak is displaying things to the screen. The only UI library I've ever liked was WPF and Microsoft deprecated that, so I thought "I should make my own!"

Editor's note: do not make your own graphics library. In the industry this is called a "Bad Move."

Of course there are a lot of important elements to a good UI library. Fortunately, I am only working on a UI library, it being good is nowhere in the plan. Regardless though, I do need a few basic features:

  • Rectangles
  • Lines
  • Text
  • Layout containers

However, there remains a question in my mind still:

How do you define an application?

Not like, etymologically. Like, how do I layout a graphical application in code. I should also note here that I'm currently using rust for this.

That might change in the future, I did consider Odin, but for now it's rust. Odin looks really cool but I don't really like how much pointer nonsense it brought over from C.

Unfortunately, I am not good enough at rust to figure out the lifetime shenanigans necessary for a good single application struct that holds all the necessary data.

Anyway, let's start with text because rectangles and lines sound boring.

Text

I think what I'm going to do is start with two kinds of text constructs, GlyphCanvas and GlyphRun. A GlyphCanvas is a rectangle canvas with a defined width and height that renders characters in order and breaks any overflowing characters down to the next line. A GlyphRun will render a set of characters in order until it runs out.

They sound similar but the actual rendering techniques will likely vary a little.

GlyphRun

The idea here is to programmatically render this as much as possible. I made an early version of this when dicking around in fig, and the idea is to give a render pass an indexed vertex buffer of one rectangle and a uniform buffer with the text and metadata like size and positioning. Then the GPU can handle selecting a character from the font texture atlas and rendering it to that instance of the glyph rectangle. This is probably a stupid way to do it but it worked so I think I'm going to stick with it.

What needs to come next is figuring out how to deal with the render pass part behind the scenes. I want to be able to instantiate an application state struct with text rendering enabled and just add glyph runs to be rendered. Mostly what I need to figure out is how to deal with a glyph render pass. I kind of assume I can create a single render pass and do draw calls for each glyph run (or more likely some kind of batched draw call)?