text quality

hi

I’ve tried text in texture mode (with increased resolution) and in polygon mode with multisampling. This last option gets me decent results (aside from the fact that the app crashes with opengl driver error whenever i maximize if I have multisampling enabled), but the text is still not as good as the text rendering of an operating system.

Now, I suppose I know why this is happening. In the case of the texture mode it’s because we are scaling pre-rendered text, whereas normally you would render geometry information on a bitmap, so there’s no hinting at all. In the case of the polygon, well it should look ok, but I guess that graphic cards aren’t as optimized for rendering geometry in small bitmaps as normal antialiased text renderers.

Anyway, I’m wondering if there’s any way to get real crisp text: i.e: rendered by a text render to the native resolution that is being shown. For example, is there a way to tell the text node to render to a 100x50 pixels texture and then show that texture in exactly that size, without any kind of filtering? That way there would be no scaling at all, and I would just have to recalculate the sizes of my textnodes whenever the size of my app changes.

Yes, this is possible, but a little tricky. The trick is to set the font’s pixels_per_unit to match exactly the onscreen size of your rendered font. This means you have to compute this value based on your window size.

You can also play games with the filter modes–try setting text-minfilter to different options, or directly manipulate the settings on the font’s DynamicTextPage object (which is, after all, just a Texture). But if you really want your text to be pixel-perfect, the filter modes are just a band-aid; you need your text font to match up pixel-for-pixel with its placement onscreen, which means you need to calculate pixels_per_unit precisely.

Treeform in particular has been leading the quest towards an easier way to get pixel-perfect font rendering; try searching for “pixel perfect” in the forums.

David

Alright, then. Does Panda account for the difference between directx and opengl alignment that this thread talks about? discourse.panda3d.org/viewtopic.php?t=5268
Since the thread is pretty old I figured maybe it’s fixed now.

Er, no, to my chagrin, I’ve avoided thinking about that particular problem since that post, and no one else has brought it up again. :frowning:

David

Ah no worries, the fix should be easy. I’ve gotten pretty good results modifying the snippet that you had modified in this thread.

    #define PPU 128.0f
    #define SCREEN_HEIGHT 600

    historyText = new TextNode("node name");
    PT(DynamicTextFont) font = new DynamicTextFont (Filename("Vera.ttf"));
    font->clear();
    font->set_pixels_per_unit(PPU);
    font->set_minfilter (Texture::FT_nearest);
    font->set_magfilter (Texture::FT_nearest);
    font->set_texture_margin(1);
    font->set_scale_factor(1);
    historyText->set_text("");
    NodePath textNodePath = window->get_aspect_2d().attach_new_node(historyText);
    textNodePath.set_scale( PPU * 2.0f / SCREEN_HEIGHT );
    textNodePath.set_pos(-1.2, 0, 0);
    historyText->set_text_color (1,1, 1, 1);
    historyText->set_shadow(0.02,0.02);
    historyText->set_shadow_color(0, 0, 0, 1);
    historyText->set_font (font);

I found that if I used set_texture_margin(0) I got glitches everywhere and if I used set_texture_margin(2) I got the following assertion in dynamicTextPage.cxx:

void DynamicTextPage::
fill_region(int x, int y, int x_size, int y_size, const Colorf &color) {
  nassertv(x >= 0 && x + x_size <= _x_size && y >= 0 && y + y_size <= _y_size);

Which worries me a little. But with a value of 1 all works fine.

My screenshot still has a problem though, the shadow offset is sometimes 3 pixels, sometimes 2 pixels, which is good on one hand because it means i’m getting perfectly aligned pixels but on the other hand it’s a problem because the shadow offset should be the same everywhere, either 2 or 3 pixels. Anyway, I have a theory, it’s probably related to a negative numbers bug probably because the offset is 2 pixels to the left of the central axis and 3 pixels to the right. I’ll try to fix it.

EDIT: scratch that, its not sign-related

Sorry for doublepost.

Do you have any idea why set_antialias() doesn’t have any effect? I’m issuing this call right after that snippet and before set_text();

textNodePath.set_antialias(AntialiasAttrib::M_none);

I’ve tried M_none, 0, M_always, and I always get the same smooth, default anti-aliasing, shouldn’t that work?

Are you sure you have a framebuffer configuration with multisamples enabled?

Ah doh. I mistook freetype antialias with generic antialias.

I read that in another thread and didn’t notice the name is slightly different. thanks.