• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
gfxCahd

Text rendering - Minification?

12 posts in this topic

Ok, so I've implemented my own BitMap font system. Using the textures and description file produced by Angel Code's BMFont (http://www.angelcode.com/products/bmfont/) I can display properly formated text (kerning included!) in my project. Since I'm also using a custom spritebatch class, the text rendering is rather fast too.

 

There is just one problem: It looks like utter shite.

You see, I use a font with character size at 50 pixels. Then in my project I use various sizes (all smaller than the original font) which i achieve by scaling. Then I also support various resolutions (yet more scalling for my font). The final result is barely legible (moth-eaten text without mipmaps, smudged-out text with mipmaps).

 

Now before someone suggests SDF (Signed Distance Field) text, I must point out that, although being able to render almost any size of text, at any angle, is a remarkable thing, that my needs consist entirely of displaying scaled-down text, without any rotation. And, I've seen mention that SDFs are not that great with rendering minified text.

 

Another thing I've noticed is the positioning of the individual glyphs on screen. Integer positions are supposed to give a much cleaner result, but how do i manage to do this when I also have kerning involved?

 

So, what is the best way to render minified text?

Edited by gfxCahd
0

Share this post


Link to post
Share on other sites

Trilinear filtering might help with the mipmapping a little perhaps.

 

However, probably the best/easiest fix is to generate some more fonts which you can switch to when you're rendering. So instead of a one-size-fits-all 50 pixel source, have a 15 pixel, a 30 pixel and a 50 pixel version. You might even find that your chosen typeface looks poor at 15 pixel, so you might need to use a different font for very small characters, one which has been optimised specifically for small sizes.

1

Share this post


Link to post
Share on other sites

Trilinear filtering might help with the mipmapping a little perhaps.

 

However, probably the best/easiest fix is to generate some more fonts which you can switch to when you're rendering. So instead of a one-size-fits-all 50 pixel source, have a 15 pixel, a 30 pixel and a 50 pixel version. You might even find that your chosen typeface looks poor at 15 pixel, so you might need to use a different font for very small characters, one which has been optimised specifically for small sizes.

 

Hm, I wonder, maybe there is a way to use smaller fonts as mipmaps? I mean, I generate one large 64pix font texture, then use a 32pix, 16pix, 8pix etc font generated by BMFont, and put these in the original 64pix texture as its mipmaps.

 

Or do character details (width, xadvance etc...) do not change linearly with scalling?

 

Edit: Gah..., after a bunch of experimenting, I can't get BMFont to give a consistent layout of the glyphs. It keeps rearranging them when I specify different texture sizes. I think I'm doing everything correctly (64pix font in a 512x512 texture with 8 spacing on either side of each character, then a 32pix font in 256x256 texture with 4 spacing, but BMFont keeps changing each characters possition.!.....)

Edited by gfxCahd
0

Share this post


Link to post
Share on other sites

I implemented BMFont rendering in an OpenTK project, and remember having to tweak the output settings a bit to get the text to look good.  I don't have the config file I ended up using handy, but I remember it taking some experimentation.  The end result is pleasing to me, with both min- and mag- (I just let OpenGL create the mipmaps).  Of course, I suppose it depends on how much scaling you are doing.

 

Maybe you can post some screen shots of your results, maybe someone might see something there?

 

EDIT: ah, found the config I'm using:

# AngelCode Bitmap Font Generator configuration file
fileVersion=1

# font settings
fontName=Open Sans
fontFile=
charSet=0
fontSize=24
aa=1
scaleH=100
useSmoothing=1
isBold=0
isItalic=0
useUnicode=1
disableBoxChars=1
outputInvalidCharGlyph=0
dontIncludeKerningPairs=0
useHinting=1
renderFromOutline=1
useClearType=0

# character alignment
paddingDown=0
paddingUp=0
paddingRight=0
paddingLeft=0
spacingHoriz=1
spacingVert=1
useFixedHeight=0
forceZero=0

# output file
outWidth=256
outHeight=256
outBitDepth=32
fontDescFormat=1
fourChnlPacked=0
textureFormat=png
textureCompression=0
alphaChnl=0
redChnl=4
greenChnl=4
blueChnl=4
invA=0
invR=0
invG=0
invB=0

# outline
outlineThickness=0

# selected chars
chars=32-126

# imported icon images

Edited by laztrezort
0

Share this post


Link to post
Share on other sites

Your spacing is too small (1 pixel). If you want mipmaps the spacing should be at least 8. (Personally I think mips 0, 1, 2, are enough, anything smaller is completely useless, so a spacing of 4 should be good enough).

0

Share this post


Link to post
Share on other sites

I don't have the complete code base in front of me, but I believe these are the settings that worked fine for my rendering implementation (likely I was using texture clamping).  That said, the exact settings depend on the rendering methods used.

0

Share this post


Link to post
Share on other sites

How are you generating the mipmaps?

If you are letting Direct3D or OpenGL do it for you it is expected to look like crap; they default to a box filter.

 

If you have to do it through image filtering, the best you can use is a Kaiser filter.

But for best results, the tool should be able to redraw all the font images at half resolutions and create a mipmap chain for you.  If this is not possible, use a Kaiser filter for sharper scaled-down text.

 

 

L. Spiro

0

Share this post


Link to post
Share on other sites

Hi Spiro.

 

I generate the font by converting the png file I get from BMFont to dds,

using Paint.Net, A8R8G8B8, with supersampling for the mipmaps.

I am pretty sure this method creates the best mipmaps possible, but please correct me if I'm wrong.

 

(Actualy, I first edit the BMFont png file to premultiplied alpha, using Pixelformer,

as I do all my drawing with a blendstate that expects premultiplied textures.)

 

In my shader, I use trilinear filtering, and a mipmap bias of -0.65f.

This does help a bit, but not by much.

 

Here is the result:

example.png

 

I have come to the conclusion that there are two problems. First, the mipmaps are awful:

font.png

 

Mipmap 1 is visibly worse than what BMFont would create at half of the originals pixel width.

Also the subsequent mipmaps are worse than useless.

 

 

Then there is the fact that screen positioning plays a very big role in how the final text will appear. And it is not a simple matter of setting the glyph positions to integer values. For example, the left square bracket '[' looks good when you force its left coordinates to integers, while the right square bracked ']' needs its right coordinate to be an integer. Nevermind how all this would ruin the effect of kerning.

Edited by gfxCahd
0

Share this post


Link to post
Share on other sites

To get proper mipmap usage you need padding between the glyphs that match the number of mipmaps. For example if you have 2 mip-levels (original image + one scaled to half size), the glyphs must be aligned on 2-pixel boundaries and must have two pixels padding between them (to avoid texture filtering to cause bleeding of adjacent glyphs in the texture).

If you need another mip-level, that requires 4-pixel alignment, and the next 8 pixels.

 

If your original glyphs are 32x32 and you allow two extra mip-levels that will be 16x16 and 8x8 and smaller glyphs than that probably aren't readable anyway so I wouldn't allow smaller mipmaps but let them pixelize if they get smaller (so just create the texture with only 3 mip-levels).

1

Share this post


Link to post
Share on other sites

^ Yeah. In the font i posted, I use a spacing of 4 pixels (on either side), and in my project, I specify that only the first 2 mipmaps are used (D3DX10_IMAGE_LOAD_INFO MipFilter = 3)

Edited by gfxCahd
0

Share this post


Link to post
Share on other sites

please correct me if I'm wrong.

Compare your results to mine and decide for yourself.
 
font2.png

There are many factors in making proper mipmaps.
#1: A proper and sharp filter, such as a Kaiser filter. Judging by your first mipmap, Paint.NET uses a pretty crappy down-sampling filter. I judge based only on the first mipmap because you can’t make mistake #2 with it, which is-
#2: Every mipmap level must be calculated from the original full-sized image. It is a mistake to halve the image, then halve that image, then halve that image etc. down to 1×1. Halve the main image. Then fourth it. Then eighth it.
#3: Premultiply alpha before generating the mipmaps. But you are already doing this.


There is no real solution to on-screen positions. Your focus should only be on the mipmap quality. Use my image and check the result.


L. Spiro

Edited by L. Spiro
1

Share this post


Link to post
Share on other sites

Wow, that made a difference, thanks!

Using the Nvidia plugin for photoshop, with the Kaiser filter and the format 32.32.32.32f ABGR 128bpp

I got a result almost as good as yours. What software are you using?

 

#2: Every mipmap level must be calculated from the original full-sized image. It is a mistake to halve the image, then halve that image, then halve that image etc. down to 1×1. Halve the main image. Then fourth it. Then eighth it.
 

 

Hm, doesn't the NVidia plugin do that automatically?

0

Share this post


Link to post
Share on other sites

Photoshop CS2.
Its normal reduction routine is very similar to a Kaiser filter (or is a Kaiser filter) but you have the option of adding a sharpening pass after it. A Kaiser filter alone is usually enough but you can also resharpen each mipmap for slightly better results.
 

Hm, doesn't the NVidia plugin do that automatically?

I would assume so.


L. Spiro

Edited by L. Spiro
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0