Sunday, April 13, 2008

Faster Text Rendering

I spent a chunk of today speeding up text rendering for Kudos 2 (and all future games).
If you are an beginner games coder you may be used to rendering(drawing) text like this:

WorkOutWhereToDrawText
SetTheCurrentFont
DrawText
WorkOutWhereToDrawText
SetTheCurrentFont
DrawText
etc...

But that doesn't cut it if you want to run really fast and lower your system requirements. Even with ninja video cards actually *drawing* anything is very slow. You don't want to tell the card to actually 'commit' any pixels until you:
a) know they will be seen and
b) have enough pixels ready to draw that its worth interrupting the card to give it more data.

Rendering text isn't a simple matter. If you have a block of text that needs word wrapping there are tons of calculations to do. How much are you scaling the text? what character equates to what part of what image, where can be break words in half? how wide was that last character, have we applied any kerning or leading to the current font, or alpha blending etc etc etc.

Because text tends to not change 60 times a second, it makes sense to 'cache' this stuff. That means that you do all these calculations, work out the final data, and then store it, for use later on. It's like preparing a quick and easy script for the video card so it knows what to do without lots of tedious re-calculating of stuff that doesn't change.

Of course *some* text is changing more often, and some windows appear in front of others, and some groups of text share the same font, and some don't... It all ends up a hideous spiders-web of code that looks a bit of a mess, but is in fact quite cunningly designed so that the amount of 'on the fly' calculating of what goes where is minimised. The player doesn't know any of this, its all transparent and hopefully just *works*. But that doesn't mean it doesn't take hours of fiddling, and measuring, and more fiddling, to get it all right.
Som coders render text out to a separate texture and just 'copy;' the finished text to the screen every frame. I have found that this works great on 95% of video cards. The other 5% just crash, without warning (cheers intel). Like most games coding, you spent 50% of the time catering to the edge cases of 5% of the hardware setups. That's why coders love consoles.