Custom font with D3DX

Started by
23 comments, last by MikeVitt 18 years, 4 months ago
If you want to do cool tricks with your text, you should look into using sprites with dynamic vertex buffers. It is THE fastest way to render dynamic (changing every frame) quads. It's no different for text than for sprites; my text class actually just has length(String) number of sprites inside it. I've posted the details before, as have many others... I can't get into it all now, but make sure you're using the right vertex buffer flags or you can get into trouble.

For combining font images, I use two custom programs. First I take my alphabet string (100+ characters of your choice) and paste it in Photoshop in the font I want and rasterize it. My first custom ('Graphics Destructor') program splits the long image into individual files. The second custom program (Graphics Processor) recombines the images into a 1024x512 texture (sorry, I got the size wrong before). Lastly I use Photoshop to tweak the image, add a drop shadow, and fix any stray pixels. I then create a sprite for the text (using my Sprite Editor) and set up the different 'profiles'. For instance, I might have a 'red' profile or a 'fade in' profile or a "50% transparent" profile, etc. which describes how the text is rendered. This is the same as for all sprites in the game.

As a side note, the Graphics Processor is pretty cool; if you have a 300 frame animation, it can average the frames together to make an animation of any arbitrary number of frames and output a PNG. I get motion blur and save memory; very very useful. Unfortunately this program is really annoying to install or else I would share it; it requires registry keys and the .NET framework. Let me know if you want to tackle it. I can't say enough about the power of custom tools for things like font engines and other textured quad tasks.

The alphabet string is:

"!â#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ˆ·®™©¼½¾¿"

Here is the final output alphabet PNG file (using Arial for now. The drop shadow is a little sloppy, I might fix it later, but the text is usually scaled down enough or rendered additive so you don't easily notice the flaws):


If you want you can get the text file that has the character widths (using yet another custom program, 'Font Measurer'. Each line is the width of the character in pixels so you can know how far to 'scoot over' as you place the characters. Not necessary if you use a fixed width font, but it might look inferior.

www.planetflux.com/flux2/fontwidths.txt

Here is a screenie of my next project, Flux 2 (still in its infancy, dont take anything from this shot), but it does demonstrate the text being used some different ways. I had to resize it down a bit for file size:



Hope this helps.
Advertisement
Here's another one for you to try (Century Gothic), used for my (about to be released) game Impact. The alphabet string is the same, no postprocessing effects.



and the corresponding text file:

http://www.planetflux.com/flux2/impactfont/fontwidths.txt
I forgot to add, the most tedious part is the spacing. After you paste the alphabet string into Photoshop, you have to rasterize the text onto a layer. Then what I do is make a pattern and fill the background in. The pattern is a 64x64 box with marks down the center so that I can align each character (and then delete the background.) Then I manually position each character in the center of each box. You really have to do this manually because you can't just crop each character. For instance, 'c', 'p', 'q', 'g', 'b', 'o', and 'd' should, I believe, be centered such that the 'o' part of each letter would overlap if they were overlayed. This might not happen if you just auto-cropped and saved/centered each character.
My approach is more general and much easier to get going, as with all things you have to find the right solution for your project.

Bitmap Font Builder creates a full font page, but also generates the widths of each character so they aren't rendered as monospace (though you can do that as an option too).

Then when you render a string it just draws a textured triangle sourcing the appropriate subrect of the font. Though I use texture triangles you could use D3DXSprite instead if you prefer, they essentially do the same thing.

The biggest limitation of this approach is that you're somewhat limited in how much you can mess with the font. Since the font widths are generated from the basic font, if you added a really wide dropshadow it might not look quite right.

At any rate, the full source is included in mine so you can check it out to see how I do it. If nothing else it might give you some ideas on the calculations involved.
Stay Casual,KenDrunken Hyena
Quote:Original post by DrunkenHyena
Since the font widths are generated from the basic font, if you added a really wide dropshadow it might not look quite right.

Could you not just add the drop shadow after you perform the measurements? Or is the measurement performed at run time? Or maybe you could just have two textures and use only the basic one (no shadows) to compute spacing for BOTH types.
That’s nice font, I wish I could paste mine…

Anyways, I have created my font with a full 512x512 image. The widths I tried to use screwed the spacing all up. I used them wrong or something. I added the widths to the spacing each time I iterated through the string and drew a character. What’s the formula to get the font’s to space right? I guess I could figure that out after trial and error.

But um, I use ID3DXSprite because it’s simple. I could use a quad or triangle strip of some kind. I need my font to just font…. and to change colors. I currently use the color parameter in the sprite’s draw function. Lame, but it works.

I want the text to be animated. I need certain strings to zoom, scroll and fade into a scene. Scrolling is easy, zooming, I guess, would be adjusting sprite size and the fading would probably do with alpha. I use a BMP instead of TGA now.

I’m trying to get the alpha channel of the bitmap blurred off the edges of the font a little so that the black background of the bitmap will be used as a shadow. I don’t think it’s working. I mean, the back buffer is clear to black, so I guess I have to change it to something else so I can make sure the shadow appears. I would like to use the same cheap shadows for other things to.

I guess if I really wanted too! I can look up text effect and tricks in Java or &#106avascript and probably find thousands of examples to do what I want. Most of them I think I might be able to clown up.

This brings me to my next point, animation frames. I would like the font to be animated because it goes with the transitions amongst other stuff. All these fades and things or bogging me down and I’ve been having problems completing a technical design on the topic because each test looks like crap and usually doesn’t work.

I’ll start with the font because that is the most complicated animation. Basically, I need to animate the text scrolling in, bounce a bit, and lastly scroll out. Other cool stuff happens too. But I have lots of transitions, do I really need to hard code them? If I do, how? I don’t have to make a ton of if’s so I figured I would use a global array defined in the program or else were for the effect. Each frame has a time value and a list of properties. Weather or not if the frame does anything with them, they still have them. Then I just interpolate between the frames. I only change the frame indices for interpolation if the time has passed the time of the second interpolant (frame B). Sound good? I know I didn’t explain much but animation issues keep holding me back. I must lean more.

Cool Effect 1:
I used the chiller font to make this really creepy FPS counter. Every frame I randomly generates two numbers between -3 and 3. I added those numbers to the X and Y values of the string (16 and 8) and also randomly generated the red only color from 96 – 220. The font jumps around a lot and with the constant color change made it look like it was almost distorting. Pretty cool but if got really annoying after a bit.
Take back the internet with the most awsome browser around, FireFox
Quote:Original post by MasterWorks
Quote:Original post by DrunkenHyena
Since the font widths are generated from the basic font, if you added a really wide dropshadow it might not look quite right.

Could you not just add the drop shadow after you perform the measurements? Or is the measurement performed at run time? Or maybe you could just have two textures and use only the basic one (no shadows) to compute spacing for BOTH types.


The font size measurements are done from the actual font glyph so it won't take into account any changes made to the bitmap after it's generated. Relatively small changes work well, the drop shadow in your font page would probably work because it doesn't add much relative to the size of the font. More elaborate things (which your system probably handles) are unlikely to work. A really long drop shadow, for example, would get drawn over by the next characters which probably isn't the desired effect.

I have a much better system planned out, but this one is great for simplicity and turn around time. You can get some decent effects out of it too as long as you keep its limitations in mind.

Stay Casual,KenDrunken Hyena
Quote:Original post by sakky
That’s nice font, I wish I could paste mine…

Anyways, I have created my font with a full 512x512 image. The widths I tried to use screwed the spacing all up. I used them wrong or something. I added the widths to the spacing each time I iterated through the string and drew a character. What’s the formula to get the font’s to space right? I guess I could figure that out after trial and error.


How did you get the font widths? Are you sure they're right? If you look at my source you can see how I calculate the rectangles and such and copy that.

Quote:
But um, I use ID3DXSprite because it’s simple. I could use a quad or triangle strip of some kind. I need my font to just font…. and to change colors. I currently use the color parameter in the sprite’s draw function. Lame, but it works.


If you're comfortable using D3DXSprite then that's fine. Once you have everything working, if it looks like you need to optimize things you can look into other solutions then. D3DXSprite performs pretty well though so I wouldn't worry.

Quote:
I want the text to be animated. I need certain strings to zoom, scroll and fade into a scene. Scrolling is easy, zooming, I guess, would be adjusting sprite size and the fading would probably do with alpha. I use a BMP instead of TGA now.

Most standard text system focus on standard text rendering, left to right, top to bottom (for Western languages anyway :) ). It sounds more like you're interested in Demo-style effects. You can still use the same basic methods, but rather than thinking of them as text, think of each character as an individual sprite that just happens to make a word.

Quote:
I’m trying to get the alpha channel of the bitmap blurred off the edges of the font a little so that the black background of the bitmap will be used as a shadow. I don’t think it’s working. I mean, the back buffer is clear to black, so I guess I have to change it to something else so I can make sure the shadow appears. I would like to use the same cheap shadows for other things to.


If you want nice shadow effects you really need them as part of the texture and they're fairly easy to do in Photoshop. If you have the background cleared to transparent, adding a drop shadow should be nicely blended for you. You need to make sure you save the image in a format that supports alpha though. I recommend PNG.
Stay Casual,KenDrunken Hyena
Nearly any font system you're going to implement in a modern 3D game is essentially going to boil down to rendering bitmapped fonts using textured quads. Even the the D3DX library's font stuff does it this way, although the creation of the bitmaps is done behind the scenes. The main alternative would be to lock your rendering target and draw your font glyphs directly onto it, but that approach would suffer some pretty major speed penalties on a lot of hardware.

Essentially what goes on behind the scenes is that the font renderer will take a TrueType font and render its glyphs in a particular format (size, bold, underline, etc...) into a texture. Then that texture is used to render a bunch of quads on the screen. I personally rolled my own font renderer using the FreeType font rendering library. Works quite well.
Quote:Original post by Shinkage
I personally rolled my own font renderer using the FreeType font rendering library. Works quite well.


A bit of an aside, but what's so special about FreeType? I understand it's cross-platform, but I've heard people rave about it for projects that aren't intended to be crossplatform. So what's the deal? I scanned (briefly) the feature list and nothing jumped out at me. Is it really so much better than using the Win32 calls? If so, why? Inquiring (and lazy) minds want to know!

Stay Casual,KenDrunken Hyena

This topic is closed to new replies.

Advertisement