Programming with OpenGL #4

Posted by Mordi on April 25, 2012, 2:23 p.m.

The last few days I've been working on rendering fonts. At first I had trouble with aliasing and foreign characters. These have now been fixed. Another problem was that font-rendering was terribly slow. What I was doing at first was simply generating each glyph (character) and a texture of the glyph at runtime every time it was drawn. Therefore, I figured that it would be better to just render all the glyphs when the font loads, and then use these textures to draw the text. I managed to get it working pretty quickly, and it's much faster now. However, I still need to clean it up. Right now, each glyph has it's own texture, which means that I have 223 textures for the engine to work with. I should rather render all of them to a single texture, and have a map of them to use when drawing the font. That's where I am right now.

Here's a picture of it rendering 223 texture-characters of Coolvetica. Before, this would mean about 15 frames per second max on my machine, but now it can handle it easily at 60 (won't go over 50 in my case, since I am connected to my 50hz TV).

Stay tuned for more.

Comments

Rob 12 years ago

Quote:
15 FPS for drawing fonts

wat

Mordi 12 years ago

Quote:
…generating each glyph (character) and a texture of the glyph at runtime every time it was drawn.
This.

TheVladR 12 years ago

You definitely need a Texture Atlas with all characters. Created Offline, not even at start-up, so you can just load the texture at start-up.

I`m guessing the next feature will be variable width of each character ? You`re up for some sick fun there - to get it working nicely, that`s for sure :-)

ludamad 12 years ago

It was funny creating my current RPG engine with pathfinding, procedural room generation, enemy collision avoidance, fog of war … and seeing the performance bottleneck be drawing of text. Luckily I was able to speed it up by storing each character in an OpenGL texture, but still. Good point about rendering them all to one texture. Definitely will help performance with not having to call texture bind as often.

TheVladR 12 years ago

You have to understand that you have been switching the texture up to hundred times per a line of text.

That`s way too much CPU-intensive. It was slowing you down more than pathfinding and everything else, since those tasks were separated from GPU. However, setting up current texture and drawing a character creates a GPU dependency, where CPU just stalls doing nothing until the render request has been executed.

That being said, there`s only so much free time and you have to weigh in the gains. Is it really worth it spending possibly several days to get it to run at 200 fps ? Wouldn`t it be better if you put some other feature in the same timeframe ?

ludamad 12 years ago

VladR: I understand these things just fine, hence why I optimized once I observed performance is too low. (Optimized only when I saw it was the bottleneck). Also, optimizing so the textures wouldn't switch would be a relatively trivial change… I don't see your point.

TheVladR 12 years ago

If you mean the most common letters, then yeah - that`s trivial. It still doesn`t make it much faster unless it`s all in one texture.

But as I said, if the performance is OK on machine with minimal spec, then just ignore it and get to it, when other new features will bring the performance below acceptable level.

Mordi 12 years ago

Quote:
You definitely need a Texture Atlas with all characters. Created Offline, not even at start-up, so you can just load the texture at start-up.
Not really. Creating the spritefont takes about 0.25 seconds, and having the ability to switch fonts out just by loading a different font-file is very useful, especially while developing it. Also, this means I can switch out the font while the game is running.

Mega 12 years ago

You're making great progress, Mordi. A little tip when rendering anything:

Allow only one call max per frame to glOrtho/gluPerspective. You may have this covered, but it's a common mistake that costs cycles like crazy.

For anti-ailiasing, you can do one of three things:

> Use a bitmap font (from an image) with an alpha channel (And blend with GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

> Use a TTF font loader

> Render the fonts to a texture and use afast Cubic interpolation filter on it.

Use a 512x512 map for the font texture, then render the whole font to the map if you want. Using GL's image format can be a bit of an annoyance in that area though.

Mordi 12 years ago

Good tip. Right now I'm only calling it once at initialization, I think. But I was thinking about looking at some 3D-rendering when I get a little further.