<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">An initial prototype of a "font strike" generator landed in the freetype demo. This renders selected characters of a typeface into a texture album at a given point size. In other words, it makes a bitmap font from a Truetype outline font. Everything about this is crude and incomplete, but there we are, it looks like text.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">I loaded the texture album into the ground plane texture just to be lazy, but it kind of cool with a Matrixy feel. The texture album format is extremely primitive. There is just one column of characters and the same width for every glyph. The widest glyph (usually W) determines the album width. This wastes a lot of texels but we can revisit that at any time. Memory is cheap right?</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Actually, no. GPU texture memory is really precious. It is relatively small and more expensive than ordinary DRAM. And there are an awful lot of different things we want to load into it. So we need to be miserly with passing it out, especially when there can be quite a few typefaces at different sizes loaded at once.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">I'm torn about what memory format to use. I laid it out this for now with X increasing towards higher memory, which requires flipping Freetype's row layout upside down, and the album shows up with 'a' below 'b'. OpenGL has a slight preference for thinking about things that way, and it pushes the annoying flip down into the loading code, otherwise it has to be done when mapping texture coodinates to the screen, making that messy thing even messier. If I did it the other way, the glyph album would read with 'b' above 'a', perhaps a little more natural. A tiny point indeed, but it does need to be settled because the effects are pretty far reaching.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">At least I don't waste much vertical space - each glyph has only as many rows as it needs. This was easy to do, so I did it. Later I have in mind a multicolumn album format where a wide glyph can span several columns, with the column width chosen so the most narrow glyphs lying in a single column do not waste much space. This will require an actual allocator for the album but I think it can be pretty simple relative to the considerable amount of texture memory saved. We also need a glyph directory to find its texture coordinates, baseline position, amount of leading whitespace, etc, which does not exist at all yet.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">For the high level organization I was able to repurpose some texture loading machinery I had created earlier to solve the problem of how to manage image assets on program start, before a GPU surface actually exists. Then images can't just be loaded straight into texture memory as is typical for an OpenGL program. Instead, we park loaded images in a big vector and reference them by index later when it is time to upload to the GPU. (This has the immediate desirable effect that if some file turns out to be missing or misspelled, the program just reports it and exits in a civilized way instead of popping up a GL window and doing the usual annoying big-flash-kaboom effect.)</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">So we end up with image index numbers, a lot like OpenGL texture numbers, and that looks like a pretty good way to keep track of lots of images. A nice benefit is, its easy to avoid memory leaks because all the images are referenced from a well known location. Well, we can leak resource indexes but somehow that doesn't seem quite as bad. The best thing is, no pointer segfaults. It seems like a good idea.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Now I am thinking, we can actually manage all kinds of things that way, not just images, so I renamed image map API as "asset map" with a view to supporting all kinds of different objects, which might not be images or textures at all. Now we have one new kind of asset, a texture album. It can have various properties to make it smart, in particular the ability to render text. I can see it acquiring other abilities as time goes by, such as the ability to re-rasterize its glyphs if the window size changes. it could respond to texture cache pressure by automatically releasing its texture resources and reloading from main memory if necessary, and it could rasterize glyphs on demand instead of all at once, to support really big character sets like Unicode. And it is friendly to introspection, like "how much total memory is devoted to render assets right now". I think this concept is a keeper.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">This very first bitmapped text rendering is not the most beautiful in the world. The characters are splotchier than I expected. I attached a image with text rendered by GLC for comparison, which is even uglier. Now I don't feel so bad. Anyway, we will see how it looks when rendered accurately onto a rectalinear pixel grid instead of being a crude bilinear scaling of a low res texture as now. A lot of the challenge of text rendering is about dealing reasonably with small point sizes, like the 12 point here. It should be possible to go right down to about 6 point and still be readable, so there is a lot of room for improvement. But this is a starting point. A usable replacement for GLC just got a little closer.</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Regards,</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">Daniel</p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "> </p></body></html>