Post tutorial Report RSS Importing Bitmap fonts into UEngine 1.x

This is a brief tutorial on how to make bitmap fonts manually and import them into Unreal Engine 1.x games like Unreal and UT99.

Posted by on - Advanced UI/HUD

Getting started:

First off this is a rather tricky thing to accomplish in Unreal Engine. I don't truly understand how the font importer expects fonts to be laid out but so far I've manged to make a few minute fonts with only minor errors that can either be fixed easily towards you're better off scrapping and starting over.

Let's look at a example:

This is the Canvas object. It imports a few default fonts.

The #EXEC directive for importing bitmap fonts in Unreal Engine always follows this format:
#exec Font Import File=(path to file) Name=(object name)

Name can be ignored, if you omit the "Name=" field, the name is defaulted to the filename of the imported object. However this is for the FONT object, the texture that is the bitmap font will be called "Texture#" where # is a number. In both UnrealED 1.0 and 2.0+ Font's can be viewed but if you try to set the texture group in the texture browser to a font name it'll act as if you set it to (All). Also font's viewed this way do not show the grid of which the characters are arranged.

Here's what a typical font looks when viewed as a texture in UnrealED:

As you can see this is the default font in Unreal engine 1 games. Licensees may replace this font however.

Also as noted before you cannot see the grid of which the font is arranged but generally speaking you can get somewhat of a feel just by glancing at the already imported result how it sort of works.

For reference: In the editor as you view a font's texture the format of the object is as follows,
Package.FontName.Texture#

Now how do you make your own font you must be asking? It's simple!

Just fire up your favorite imaging editor that supports editing images in 256 colours along with being able to manually manipulate the palette. This is important as Index 0 in the palette is the masking colour while Index 255 is the font grid definer. For this reason I use Corel Paint Shop Pro but you can also obviously use Adobe Photoshop or similar. GIMP is not recommended as I found it does not manipulate 256 colour palette's properly wither this is a bug or a bad design choice I don't know but use at your own risk.

Before you start you need to have a ASCII table with you, this will tell you which glyphs to start first. If you try to just immediately start drawing the alphabet and align it to a grid, Unreal will not import it properly as it expects characters before A B C ,etc like spaces and numerals.

To start off and to show what the palette means let's export a font, and also observe a major pitfall in doing so:

You're probably wondering: "Where's the grid!?" That's right if you export a font texture after it has been imported as a font in Unreal Engine it strips the grid internally. However do not fret, there are usable font textures available in the beta demos that have the grid intact. And no using UTPT to export the font texture doesn't work. HOWEVER you can export the font table, how this is use to you I wouldn't know but it's useful for debugging if your font's not being defined properly.

Notice the deep blue colour at Index 255 this is used to define a font grid.

Now let's look at the MedFont of the past seeing how as I stated above the beta demo does not omit the font grid:

Notice the blue lines, this defines the glyphs in a font. Unreal bitmap fonts can be monospaced or proportional. When defining a font grid you should allow a extra bit of "white space" at the right side of a glyph so that it's spaced out when you're typing.

Unreal Engine reads fonts starting from the top left to the right and down. You should start with the Space character. This is 0x20 in hexadecimal, from there go with the ! " # ,etc until you get to the alphanumerics.

Now let's look at a font I made myself:

Note how I follow the same exact formatting. This is how Unreal expects glyphs to be lined out starting from 0x20 the space character and onward. Start at the top left of the image and work your way in a straight line to the right, when you run out of space, go to the bottom and work from there until you either fill the necessary characters you want or run out of space. Use a image that's power of two or it wont be importable into Unreal Engine at all.

BE SURE YOU ARE DRAWING YOUR FONT GRID WITH INDEX 255 OF YOUR COLOUR PALETTE!!!

Here's a UTPT font table export of my font:

text code:
Character: TextureName (X,Y)-(Width,Height)
-------------------------------------------
0x00: Texture0 (0,0)-(0,0)
0x01: Texture0 (0,0)-(0,0)
0x02: Texture0 (0,0)-(0,0)
0x03: Texture0 (0,0)-(0,0)
0x04: Texture0 (0,0)-(0,0)
0x05: Texture0 (0,0)-(0,0)
0x06: Texture0 (0,0)-(0,0)
0x07: Texture0 (0,0)-(0,0)
0x08: Texture0 (0,0)-(0,0)
0x09: Texture0 (0,0)-(0,0)
0x0A: Texture0 (0,0)-(0,0)
0x0B: Texture0 (0,0)-(0,0)
0x0C: Texture0 (0,0)-(0,0)
0x0D: Texture0 (0,0)-(0,0)
0x0E: Texture0 (0,0)-(0,0)
0x0F: Texture0 (0,0)-(0,0)
0x10: Texture0 (0,0)-(0,0)
0x11: Texture0 (0,0)-(0,0)
0x12: Texture0 (0,0)-(0,0)
0x13: Texture0 (0,0)-(0,0)
0x14: Texture0 (0,0)-(0,0)
0x15: Texture0 (0,0)-(0,0)
0x16: Texture0 (0,0)-(0,0)
0x17: Texture0 (0,0)-(0,0)
0x18: Texture0 (0,0)-(0,0)
0x19: Texture0 (0,0)-(0,0)
0x1A: Texture0 (0,0)-(0,0)
0x1B: Texture0 (0,0)-(0,0)
0x1C: Texture0 (0,0)-(0,0)
0x1D: Texture0 (0,0)-(0,0)
0x1E: Texture0 (0,0)-(0,0)
0x1F: Texture0 (0,0)-(0,0)
0x20: Texture0 (1,1)-(7,10)
0x21: Texture0 (9,1)-(5,10)
0x22: Texture0 (15,1)-(9,10)
0x23: Texture0 (25,1)-(9,10)
0x24: Texture0 (35,1)-(8,10)
0x25: Texture0 (44,1)-(9,10)
0x26: Texture0 (54,1)-(7,10)
0x27: Texture0 (62,1)-(6,10)
0x28: Texture0 (69,1)-(6,10)
0x29: Texture0 (76,1)-(6,10)
0x2A: Texture0 (83,1)-(8,10)
0x2B: Texture0 (92,1)-(8,10)
0x2C: Texture0 (101,1)-(6,10)
0x2D: Texture0 (108,1)-(8,10)
0x2E: Texture0 (117,1)-(5,10)
0x2F: Texture0 (123,1)-(7,10)
0x30: Texture0 (131,1)-(10,10)
0x31: Texture0 (142,1)-(9,10)
0x32: Texture0 (152,1)-(10,10)
0x33: Texture0 (163,1)-(10,10)
0x34: Texture0 (174,1)-(10,10)
0x35: Texture0 (185,1)-(10,10)
0x36: Texture0 (196,1)-(10,10)
0x37: Texture0 (207,1)-(10,10)
0x38: Texture0 (218,1)-(10,10)
0x39: Texture0 (229,1)-(10,10)
0x3A: Texture0 (240,1)-(5,10)
0x3B: Texture0 (246,1)-(6,10)
0x3C: Texture0 (1,12)-(7,10)
0x3D: Texture0 (9,12)-(8,10)
0x3E: Texture0 (18,12)-(7,10)
0x3F: Texture0 (26,12)-(9,10)
0x40: Texture0 (36,12)-(11,10)
0x41: Texture0 (48,12)-(10,10)
0x42: Texture0 (59,12)-(10,10)
0x43: Texture0 (70,12)-(10,10)
0x44: Texture0 (81,12)-(10,10)
0x45: Texture0 (92,12)-(10,10)
0x46: Texture0 (103,12)-(9,10)
0x47: Texture0 (113,12)-(10,10)
0x48: Texture0 (124,12)-(10,10)
0x49: Texture0 (135,12)-(6,10)
0x4A: Texture0 (142,12)-(8,10)
0x4B: Texture0 (151,12)-(10,10)
0x4C: Texture0 (162,12)-(7,10)
0x4D: Texture0 (170,12)-(10,10)
0x4E: Texture0 (181,12)-(10,10)
0x4F: Texture0 (192,12)-(10,10)
0x50: Texture0 (203,12)-(10,10)
0x51: Texture0 (214,12)-(10,10)
0x52: Texture0 (225,12)-(10,10)
0x53: Texture0 (236,12)-(10,10)
0x54: Texture0 (1,23)-(9,10)
0x55: Texture0 (11,23)-(10,10)
0x56: Texture0 (22,23)-(10,10)
0x57: Texture0 (33,23)-(10,10)
0x58: Texture0 (44,23)-(10,10)
0x59: Texture0 (55,23)-(10,10)
0x5A: Texture0 (66,23)-(10,10)
0x5B: Texture0 (77,23)-(5,10)
0x5C: Texture0 (83,23)-(8,10)
0x5D: Texture0 (92,23)-(5,10)
0x5E: Texture0 (98,23)-(7,10)
0x5F: Texture0 (106,23)-(8,10)
0x60: Texture0 (115,23)-(6,10)
0x61: Texture0 (122,23)-(10,10)
0x62: Texture0 (133,23)-(10,10)
0x63: Texture0 (144,23)-(10,10)
0x64: Texture0 (155,23)-(10,10)
0x65: Texture0 (166,23)-(10,10)
0x66: Texture0 (177,23)-(9,10)
0x67: Texture0 (187,23)-(10,10)
0x68: Texture0 (198,23)-(10,10)
0x69: Texture0 (209,23)-(6,10)
0x6A: Texture0 (216,23)-(8,10)
0x6B: Texture0 (225,23)-(10,10)
0x6C: Texture0 (236,23)-(7,10)
0x6D: Texture0 (1,34)-(10,10)
0x6E: Texture0 (12,34)-(10,10)
0x6F: Texture0 (23,34)-(10,10)
0x70: Texture0 (34,34)-(10,10)
0x71: Texture0 (45,34)-(10,10)
0x72: Texture0 (56,34)-(10,10)
0x73: Texture0 (67,34)-(10,10)
0x74: Texture0 (78,34)-(9,10)
0x75: Texture0 (88,34)-(10,10)
0x76: Texture0 (99,34)-(10,10)
0x77: Texture0 (110,34)-(10,10)
0x78: Texture0 (121,34)-(10,10)
0x79: Texture0 (132,34)-(10,10)
0x7A: Texture0 (143,34)-(10,10)
0x7B: Texture0 (154,34)-(9,10)
0x7C: Texture0 (164,34)-(5,10)
0x7D: Texture0 (170,34)-(9,10)
0x7E: Texture0 (180,34)-(12,10)
0x7F: Texture0 (0,0)-(0,0)
0x80: Texture0 (0,0)-(0,0)
0x81: Texture0 (0,0)-(0,0)
0x82: Texture0 (0,0)-(0,0)
0x83: Texture0 (0,0)-(0,0)
0x84: Texture0 (0,0)-(0,0)
0x85: Texture0 (0,0)-(0,0)
0x86: Texture0 (0,0)-(0,0)
0x87: Texture0 (0,0)-(0,0)
0x88: Texture0 (0,0)-(0,0)
0x89: Texture0 (0,0)-(0,0)
0x8A: Texture0 (0,0)-(0,0)
0x8B: Texture0 (0,0)-(0,0)
0x8C: Texture0 (0,0)-(0,0)
0x8D: Texture0 (0,0)-(0,0)
0x8E: Texture0 (0,0)-(0,0)
0x8F: Texture0 (0,0)-(0,0)
0x90: Texture0 (0,0)-(0,0)
0x91: Texture0 (0,0)-(0,0)
0x92: Texture0 (0,0)-(0,0)
0x93: Texture0 (0,0)-(0,0)
0x94: Texture0 (0,0)-(0,0)
0x95: Texture0 (0,0)-(0,0)
0x96: Texture0 (0,0)-(0,0)
0x97: Texture0 (0,0)-(0,0)
0x98: Texture0 (0,0)-(0,0)
0x99: Texture0 (0,0)-(0,0)
0x9A: Texture0 (0,0)-(0,0)
0x9B: Texture0 (0,0)-(0,0)
0x9C: Texture0 (0,0)-(0,0)
0x9D: Texture0 (0,0)-(0,0)
0x9E: Texture0 (0,0)-(0,0)
0x9F: Texture0 (0,0)-(0,0)
0xA0: Texture0 (0,0)-(0,0)
0xA1: Texture0 (0,0)-(0,0)
0xA2: Texture0 (0,0)-(0,0)
0xA3: Texture0 (0,0)-(0,0)
0xA4: Texture0 (0,0)-(0,0)
0xA5: Texture0 (0,0)-(0,0)
0xA6: Texture0 (164,34)-(5,10)
0xA7: Texture0 (0,0)-(0,0)
0xA8: Texture0 (0,0)-(0,0)
0xA9: Texture0 (0,0)-(0,0)
0xAA: Texture0 (0,0)-(0,0)
0xAB: Texture0 (0,0)-(0,0)
0xAC: Texture0 (0,0)-(0,0)
0xAD: Texture0 (0,0)-(0,0)
0xAE: Texture0 (0,0)-(0,0)
0xAF: Texture0 (0,0)-(0,0)
0xB0: Texture0 (0,0)-(0,0)
0xB1: Texture0 (0,0)-(0,0)
0xB2: Texture0 (0,0)-(0,0)
0xB3: Texture0 (0,0)-(0,0)
0xB4: Texture0 (0,0)-(0,0)
0xB5: Texture0 (0,0)-(0,0)
0xB6: Texture0 (0,0)-(0,0)
0xB7: Texture0 (0,0)-(0,0)
0xB8: Texture0 (0,0)-(0,0)
0xB9: Texture0 (0,0)-(0,0)
0xBA: Texture0 (0,0)-(0,0)
0xBB: Texture0 (0,0)-(0,0)
0xBC: Texture0 (0,0)-(0,0)
0xBD: Texture0 (0,0)-(0,0)
0xBE: Texture0 (0,0)-(0,0)
0xBF: Texture0 (0,0)-(0,0)
0xC0: Texture0 (0,0)-(0,0)
0xC1: Texture0 (0,0)-(0,0)
0xC2: Texture0 (0,0)-(0,0)
0xC3: Texture0 (0,0)-(0,0)
0xC4: Texture0 (0,0)-(0,0)
0xC5: Texture0 (0,0)-(0,0)
0xC6: Texture0 (0,0)-(0,0)
0xC7: Texture0 (0,0)-(0,0)
0xC8: Texture0 (0,0)-(0,0)
0xC9: Texture0 (0,0)-(0,0)
0xCA: Texture0 (0,0)-(0,0)
0xCB: Texture0 (0,0)-(0,0)
0xCC: Texture0 (0,0)-(0,0)
0xCD: Texture0 (0,0)-(0,0)
0xCE: Texture0 (0,0)-(0,0)
0xCF: Texture0 (0,0)-(0,0)
0xD0: Texture0 (0,0)-(0,0)
0xD1: Texture0 (0,0)-(0,0)
0xD2: Texture0 (0,0)-(0,0)
0xD3: Texture0 (0,0)-(0,0)
0xD4: Texture0 (0,0)-(0,0)
0xD5: Texture0 (0,0)-(0,0)
0xD6: Texture0 (0,0)-(0,0)
0xD7: Texture0 (0,0)-(0,0)
0xD8: Texture0 (0,0)-(0,0)
0xD9: Texture0 (0,0)-(0,0)
0xDA: Texture0 (0,0)-(0,0)
0xDB: Texture0 (0,0)-(0,0)
0xDC: Texture0 (0,0)-(0,0)
0xDD: Texture0 (0,0)-(0,0)
0xDE: Texture0 (0,0)-(0,0)
0xDF: Texture0 (0,0)-(0,0)
0xE0: Texture0 (0,0)-(0,0)
0xE1: Texture0 (0,0)-(0,0)
0xE2: Texture0 (0,0)-(0,0)
0xE3: Texture0 (0,0)-(0,0)
0xE4: Texture0 (0,0)-(0,0)
0xE5: Texture0 (0,0)-(0,0)
0xE6: Texture0 (0,0)-(0,0)
0xE7: Texture0 (0,0)-(0,0)
0xE8: Texture0 (0,0)-(0,0)
0xE9: Texture0 (0,0)-(0,0)
0xEA: Texture0 (0,0)-(0,0)
0xEB: Texture0 (0,0)-(0,0)
0xEC: Texture0 (0,0)-(0,0)
0xED: Texture0 (0,0)-(0,0)
0xEE: Texture0 (0,0)-(0,0)
0xEF: Texture0 (0,0)-(0,0)
0xF0: Texture0 (0,0)-(0,0)
0xF1: Texture0 (0,0)-(0,0)
0xF2: Texture0 (0,0)-(0,0)
0xF3: Texture0 (0,0)-(0,0)
0xF4: Texture0 (0,0)-(0,0)
0xF5: Texture0 (0,0)-(0,0)
0xF6: Texture0 (0,0)-(0,0)
0xF7: Texture0 (0,0)-(0,0)
0xF8: Texture0 (0,0)-(0,0)
0xF9: Texture0 (0,0)-(0,0)
0xFA: Texture0 (0,0)-(0,0)
0xFB: Texture0 (0,0)-(0,0)
0xFC: Texture0 (0,0)-(0,0)
0xFD: Texture0 (0,0)-(0,0)
0xFE: Texture0 (0,0)-(0,0)
0xFF: Texture0 (0,0)-(0,0)
 

Note how it begins at 0x20, that's the space character. X and Y is the position in the image itself where the top left portion of the grid point is located. Width and height is the propitiation of the glyph itself within the grid point. Use UTPT's "Export font" tool to determine if Unreal is not reading your font properly.

Reminder: Bitmap Font's will ALWAYS begin with 0x20. So start your grid off with the space character FIRST then work your way in order from the space character all the way to 0xFF, use an ASCII table to guide you on this. A typical font usually spans between 0x20 and 0x7E It's tricky to make a full fledged font that supports all extended ASCII codes, so experiment at your own peril with that. A full extended ASCII font is best left with the TTFImporter usually rather than making it manually yourself as a single bitmap.

For more information about ASCII read: En.wikipedia.org It includes a ASCII chart to assist you in crafting your font(s).

Here's a example grid:

In this example grid I wrote hexadecimal values for anything that's not usually typable on a standard US keyboard.

Notice how there's some omissions from the usual chart flow. This is because for some reason Unreal doesn't map to certain ASCII codes, so be sure when designing your font you follow the flow outlined in this example image or it may not import properly past the standard ASCII codes.

If all goes well your font should work perfectly in Unreal depending on how you engineered it for example:

This is the HUD to one of my custom PlayerPawn classes I've been developing over the months, it uses the RyukaFont I made from pasting together glyphs from the font used in Heretic\HeXen. As you can notice it only covers the standard typable ASCII range of 0x20 to 0x7E so no fancy non standard characters are used in the HUD.

Points to remember:
* Use: #exec Font Import File=(path to file) Name=(object name) to import bitmap fonts
* When designing the font grid start from TOP LEFT (0,0) and proceed right until you hit the extent you are able to draw another grid segment on. Then start over from below in the same manner as you did TOP LEFT.
* Unreal Engine does not assign all ASCII codes so don't try to make a full 0x00 to 0xFF font explicitly.
* Index 0 in the colour palette is the masking colour Index 255 is the grid defining colour.
* Bitmap Fonts can be monospace or proportional depending on how you design your font.
* ALWAYS START AT 0x20! ALWAYS END AT 0xFF!
* ALWAYS USE A POWER OF TWO TEXTURE!

I hope this is helpful to anyone who reads. Good luck making fonts manually instead of using TTFImporter like "everyone else".

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: