Pixellating Fonts

I’m currently working on a side-project for which I’ve settled on a pixell-y aesthetic.

Now, in choosing fonts for the game, in order to match that aesthetic I could use an actual pixel-font.

But I’d like to try simply pixellating a standard font. And indeed, by reducing the “pixels-per-unit” setting and applying mag/min filters of “FTNearest”, I’ve found that something to this effect can be achieved!

However, I would like the font to be without antialiasing–and this is where I’m having trouble.

Specifically, it looks like antialiasing is automatically applied at some stage, resulting in that antialiasing being incorporated into the final result–see the screenshot below:

Is there perhaps some way of disabling that antialiasing? Or am I stuck with what pixel-fonts I might find…?

The rightmost image doesn’t look like nearest filtering to me… Where are you specifying it? In the text-minfilter and text-magfilter settings in Config.prc?

To make sure no antialiasing is applied to the font on the Panda end, you should also set text-scale-factor to 1 (default is 2).

Oh, it’s very much nearest-filtering–if it weren’t, the text would be blurry, without distinct pixels.

See the following screenshot comparing the two (under the same pixels-per-unit)–default filtering on the left, nearest filtering on the right:

I’m specifying it in code, with DynamicTextFont objects.

See below the way that I setup the fonts for the preceding screenshot:

        font1 = DynamicTextFont(fontFile)
        font1.setPixelsPerUnit(20)
        
        font3 = DynamicTextFont(fontFile)
        font3.setPixelsPerUnit(20)
        font3.setMagfilter(SamplerState.FTNearest)
        font3.setMinfilter(SamplerState.FTNearest)

Hmm… that doesn’t seem to help.

(Presuming that I have it correct that I should be calling “setScaleFactor” on the DynamicTextFont object, or setting a config variable named “text-scale-factor”. I’ve tried both, with similar effect–save, of course, that the latter affects all text.)

With a factor of 1, I see minimal change. With a factor of 0.1, the resolution simply decreases, giving me bigger pixels–but still of varying shades, implying antialiasing.

See the screenshot below: All three fonts used for the text there have a pixels-per-unit of 20 applied, and nearest-filtering; the left-most does nothing more; the middle sets a scale factor of 1; and the right-most sets a scale factor of 0.1.

[edit]
Here’s a simple program that demonstrates the issue; in the line that begins with "fontFile = ", just replace the filename there with one that you have to hand.

from panda3d.core import loadPrcFile, loadPrcFileData

from direct.showbase.ShowBase import ShowBase

from panda3d.core import DynamicTextFont, Vec3, SamplerState
from direct.gui.OnscreenText import OnscreenText

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        fontFile = "Berylium.ttf"
        
        self.setBackgroundColor(Vec3(0, 0, 0))
        
        font1 = DynamicTextFont(fontFile)
        font1.setPixelsPerUnit(20)
        font1.setMagfilter(SamplerState.FTNearest)
        font1.setMinfilter(SamplerState.FTNearest)
        
        font2 = DynamicTextFont(fontFile)
        font2.setPixelsPerUnit(20)
        font2.setMagfilter(SamplerState.FTNearest)
        font2.setMinfilter(SamplerState.FTNearest)
        font2.setScaleFactor(1)
        
        font3 = DynamicTextFont(fontFile)
        font3.setPixelsPerUnit(20)
        font3.setMagfilter(SamplerState.FTNearest)
        font3.setMinfilter(SamplerState.FTNearest)
        font3.setScaleFactor(0.1)
        
        ost = OnscreenText("Mew!",
							font = font1,
							pos = (-0.8, 0, 0),
							fg = (1, 1, 1, 1),
							scale = 0.3)
							
        ost = OnscreenText("Mew!",
							font = font2,
							pos = (0, 0, 0),
							fg = (1, 1, 1, 1),
							scale = 0.3)
							
        ost = OnscreenText("Mew!",
							font = font3,
							pos = (0.8, 0, 0),
							fg = (1, 1, 1, 1),
							scale = 0.3)


app = Game()
app.run()

Yeah, I guess the antialiasing is happening on the freetype end. It looks like there’s something we can pass it to force it to disable antialiasing. I’ll have to see where we can best expose that in Panda.

This seems to do the trick too, though:

ost.setTransparency(TransparencyAttrib.MBinary, 2)

Ah, hang on, there is a setting for this. Try this:

font2.setNativeAntialias(False)

EDIT: It looks like this is not properly respected in all cases. I’ll check in a fix!

1 Like

Thank you! I’m glad that there is something to this end! :slight_smile: