Crisp text for all!

Hi everybody,

while investigating ways to render crisp characters I stumbled upon the method TextFont.setRenderMode() which seems to create a wireframe, polygonal, extruded or solid version of a given font, i.e. arial.ttf.

Key to the quality of the resulting PandaNode is the point size which I empirically found to be satisfying if set to 64. This setting leaves no space between words however and space advance had to be set to 2. The code at the end of the post allows you to play around with these parameters and do more tests.

One big problem however is that not all fonts are compatible with the polygonal render mode. It appears that all fonts are compatible with RMtexture, which I presume is the default render mode and generates a flat polygon, with a rasterized version of the font mapped on it as a texture. But only relatively few fonts can be converted to polygons and I cannot find a general rule for those that work and those that do not. I.e. simple sans-serif fonts similar to arial do not work, but arial.ttf does. Other more elaborate fonts, with serif or curved do work, but rarely, i.e. times.ttf doesn’t. In the code below you’ll find a few example of what works and what doesn’t.

I hope the code below helps other struggling to get crips text. But if somebody knows how to prevent the crashes or can fix the problem that causes them, that’d be nice. =)

Manu

import direct.directbase.DirectStart
from pandac.PandaModules import TextNode, TextFont, AntialiasAttrib

## All fonts below are from a standard Windows Vista installation.
## Font that runs out of memory 
#font = loader.loadFont('/c/Windows/Fonts/OCRAExt.ttf')

## Fonts that crash Panda/Python
#font = loader.loadFont('/c/Windows/Fonts/TempsITC.TTF')
#font = loader.loadFont('/c/Windows/Fonts/upckl.ttf')
#font = loader.loadFont('/c/Windows/Fonts/times.ttf') 
#font = loader.loadFont('/c/Windows/Fonts/cour.ttf')

## Fonts that DO work!
#font = loader.loadFont('/c/Windows/Fonts/Per_____.TTF')
#font = loader.loadFont('/c/Windows/Fonts/micross.ttf') 
#font = loader.loadFont('/c/Windows/Fonts/Juice___.TTF')
#font = loader.loadFont('/c/Windows/Fonts/Maian.TTF') 
font = loader.loadFont('/c/Windows/Fonts/arial.ttf') 

font.setPointSize(64)
font.setSpaceAdvance(2)
font.setRenderMode(TextFont.RMPolygon)

text = TextNode('aTextNode')
text.setText("This is a test")
text.setFont(font)

textNodePath = aspect2d.attachNewNode(text)
textNodePath.setScale(0.05)
textNodePath.setPos(-1.0,0,0)
textNodePath.setAntialias(AntialiasAttrib.MMultisample)

run()

Cool, I didn’t know Panda supported generating that kind of text.

All said fonts work for me. The ones that crash for you work for me, but the letter “i” is garbled.

After downloading ocraext I can confirm this runs out of memory (but I assume it’s a bug in the font itself).

PS. I’m on Linux, maybe that explains it.

Breakthrough!

It might have been obvious to other people but I found only just now that TextFont.setPointSize() doesn’t just determine the quality for polygonal characters but it does also for characters that are rasterized into the textures of a TextFont object. We can therefore obtain the same visual quality of the code above using the default RMTexture render mode, bypassing the crashes and out-of-memory problems of some font (see the code below).

Adjustments -have- to be made to space advance, line height, wordwrap and scale of the resulting object for it to be acceptable. It appears that these parameters are either directly or inversely proportional to point size, i.e. with an halving of point size space advance, line height and wordwrap should halve too, but scale should be doubled. In this context a point size value of 32 seems to be perfectly acceptable for the typical font-size of the UI and text of an application. 72 might be useful only for unusually large characters. That been said, it appears that are no savings in terms of memory or font-loading time in using one value or the other.

Thank you pro-rsoft for testing the previous post’s code on Linux. It’d be good if somebody on Vista or XP could confirm this is a Microsoft-only issue. I imagine it would help Panda’s development team to know that the problem is only in the Microsoft-related portion of the font-handling code.

Manu

Point size determines how large to render the font. It is like when you choose 10 or 14 pt in Microsoft word. The reason this would have an effect on quality here, is that font rendering can scale really easily (letters are defined by math), while both rasterized fonts (2d) and polygonal fonts (3d) are defined by discrete points and don’t scale very well at all. So in this case, by setting a higher point size (rendering it bigger), you will have more resolution in the 2d and 3d fonts.

Good find!