quest for pixel perfect fonts

I am trying to get pixel perfect fonts into my game.

It seems to be much harder then it should be. I have scaled my UI to be pixel perfect with the window size but the fonts still appear blury. I think that is a combination of true type anti aliasing and panda3d upscaling them.

This is command i used to generate an egg font.

egg-mkfont -o vrinda.egg -noaa -sf 1 -palsize 256,128 vrinda.ttf -ps 14 -ppu 14

With ps and ppu equal and noAA font does look more pixely. Just like fonts you would encounter on this page and not blures panda3d normally produces. But there is still a few problems in the font texture itself. I think that can be fixed manually. Next the problem is of color why is the egg file now has blackfont. And i am enable to change its color. The texture is white. And then a deeper problem is the spacing. It looks like every second world is blured. I think this is due to space having a .5 there so it fixes itself every second word.


Is there a way to get pixel perfect fonts like you would encounter in desktop program in panda3d? I have done this in raw openGL before and drives me up the wall that it cant be done with panda3d.

Anytime you want to get pixel-perfect anything, you have to consider the scale of the object onscreen, and you have to consider the window size. By default, of course, Panda is concerned with polygons, not pixels, and all of your units are therefore arbitrary numeric units, which have nothing to do with pixels.

If you want one pixel of the texture to correspond to one pixel onscreen, you have to be sure to make the polygon that shows the texture be exactly the right size to guarantee that. With text, this means choosing the text scale appropriately, based on the window size and the pixels per unit you selected for the font.

Here’s a sample program that demonstrates this:

from direct.directbase.DirectStart import *
from pandac.PandaModules import *

font = loader.loadFont('vrinda.egg')

winHeight =
ppu = 14

tn = TextNode('tn')
tn.setText("You can't jump from an enemy zone to an enemy zone")
tnp = aspect2d.attachNewNode(tn)

scale = (2.0 * ppu) / winHeight


And here’s the screenshot from this program, when I run it:

Note that the pixels match up perfectly with the original font bitmap generated by egg-mkfont. The scale is chosen to be (2.0 * ppu) / winHeight because aspect2d has a height of 2.0 (-1 … 1), which corresponds to the full height of the window.

I don’t know why your text isn’t coming out white, but it might be a bug in the 1.5.4 version of egg-mkfont and/or Panda. Try it in the latest cvs build.


while we are on the subject of eggfonts could you explain the egg font format?

  <Group> 95 {
    <Polygon> {
      <TRef> { vrinda095 }
      <VertexRef> { 312 313 314 315 <Ref> { vpool } }
    <PointLight> {
      <VertexRef> { 316 <Ref> { vpool } }

As i understand it 95 is chr(95) ie “_” character. Then we have the square the character sits in, but after that we have PointLight?

    <Vertex> 316 {
      0.571429 0 0

does that mean that the underscore is .5714 wide?

Yes, the PointLight determines the total width of this character: how much space is given before the next character is placed.


Oh btw i get this running your code.

This is very odd i put a size meeter on the window and started resizing. And when window hit 590px in height the font was perfect. I don’t understand why optimal scale for me is at scale = (2.0 * ppu) / (winHeight-10) what is that -10 got to do with it?

I though panda3d it might have been counting the window bar or borders differently. But no every thing looks in order i took screen shot of the app to measure the viewport.

In my game i already reset the scale at the app level with self.node.setScale(2./(, 1, -2./

Maybe there is a way to reset scaling at the render2d level which would be more accurate?

Hmm. What platform are you running on? Have you tried the latest cvs version? I do know that there was a bug in the space width computation for non-standard-sized fonts for 1.5.4 and earlier, and I can imagine that this bug could cause this artifact.


windows, ill try to get cvs trunk building again.

Does it look different in OpenGL vs. DirectX?


Its been fixed in trunk. I guess it was the spacing issue.

On a side note. Does any one have good pixel perfect font that looks good at 10 or 8 px?

One of these might work (8px)[]=10&l[]=1