PDA

View Full Version : fast text rendering -- how??



pronvit
07-24-2005, 11:05 AM
is there any way to do fast rendering of _many_ chars in OpenGL? I tried some library for text rendering and it looks very strange for me that I can draw 300 strings without OpenGL with acceptable speed and can't draw 50 in OpenGL.

canuckle
07-24-2005, 03:38 PM
try putting all your characters in one texture, and drawing a bunch of textured quads

Stroma
07-25-2005, 12:12 AM
using one texture is ok, but do not use quads. lots of engines use triangles because of graphic cards triangle drawing speed and their hierarchy is built on tris.
and if will you use same text block a lot, and it is not editable, make the text a texture and draw only 2 triangle or one quad for whole text.
another issue is state changes, do not make state changes for all texts. eg. draw them all in begingui, endgui blocks. you may use only one textrure for all gui with using atlassed textures.

SeskaPeel
07-25-2005, 07:09 AM
Render your font file at a given size in a single texture (use FreeType) + render text with a quad for each char.

If you render very few strings or if all your strings use different chars, or if all your strings have different sizes, or if all your strings use different fonts, you could use a single texture for each. In all other cases, it's better to use a cached texture for a given font's chars.

Rendering quads instead of triangles don't make a difference. If you don't intend to use kerning, you can even render a quad strip.

SeskaPeel.

Dirk
07-25-2005, 07:48 AM
And the nice thing is that somebody did all the hard work for you already, see GLTT (http://gltt.sourceforge.net/index.html) and FTGL (http://homepages.paradise.net.nz/henryj/code/) . :)

SeskaPeel
07-26-2005, 04:16 AM
Yes, except that it implements texture cache very poorly, and doesn't provide grid fitting support.

It should take two days to do all the work properly from scratch (well at least that's what I spent).

SeskaPeel.

Stephen_H
07-26-2005, 06:04 PM
I'll have to agree with Seska on this, having written my own code after examining the other text libraries.

If you're after speed, roll your own font engine. Other font engines I've looked are just so general (which can be both a good/bad thing) that performance can suffer and store a ton extra information in memory than they need to.

Packing all your font characters into a single texture is a good idea. Rendering whole phrases/lines of text into a texture so you can render lots of characters in a single quad is a good alternative option. If you search back far enough you'll find a longish thread dicussing which option is better.

tfpsly
07-27-2005, 12:12 AM
You might want to try Angel Studio\'s Bitmap Font Generator (http://www.angelcode.com/products/bmfont/) : given any trutype font, it will generate an optimized texture and a text file describing each character.
Each character takes as small space as possible in the texture.

http://www.angelcode.com/products/bmfont/images/font.gif

They give pseudo code to display their font:

// Compute the source rect
Rect src;
src.left = ch.x;
src.top = ch.y;
src.right = ch.x + ch.width;
src.bottom = ch.y + ch.height;

// Compute the destination rect
Rect dst;
dst.left = cursor.x + ch.xoffset;
dst.top = cursor.y + ch.yoffset;
dst.right = dst.left + ch.width;
dst.bottom = dst.top + ch.height;

// Draw the image from the right texture
DrawRect(ch.page, src, dst);

// Update the position
cursor.x += ch.xadvance;It took me maybe half an hour to create the font, to edit the texture to add a contour to each char, and to implement the rendering code into my engine.

ZbuffeR
07-27-2005, 04:56 AM
About such packed texture atlases, watch out for mipmapping, it will bleed horribly between chars. Not everybody needs to scale down text, but if it is your case, take care of this.

And beware of the scale up : linear filtering will make it bleed too if your texcoords aren't perfectly perfect.

SeskaPeel
07-27-2005, 07:04 AM
By generating your own texture, you can specify your desired pixel height, and disable completely bi/tri linear filtering, by generating on the fly a new texture if the height of your text change dynamically.

Even with a complex sorting algorithm to pack the glyphs the best possibly in the texture, I achieve real time performance of the texture generation up to 1024 * 1024 resolution.

And linking Freetype will give you the best rasterizer possible (avoiding all patent problems with their auto-hinter), an excellent stroker to outline your chars, and pair kerning too. What's more, their rasterizer handle proper grid fitting with any kind of 2*2 matrix (non uniform scaling, rotation, and shearing can be a plus if you need perfect oblique text rendering).

But, obviously, half an hour is better than 2 days. You'll always have to choose between implementation time and features.

SeskaPeel.

SeskaPeel
07-27-2005, 07:05 AM
I almost forgot to mention that they support Unicode, chinese and arabic glyphs, etc.

All this in a conformant way (arabic actually needs a bit more work).

SeskaPeel.

Stephen_H
07-27-2005, 10:42 AM
Actually, I've tried both FreeType2 (without the hinter enabled) and using the Windows GDI function to rasterize the font glyphs. For smaller characters (about 6-12 pixels in height) I found that the Windows function produced a lot better output. For larger characters, there was no real noticeable difference. This was about 2 years ago when I did this, so perhaps FT2 has improved since then...

pronvit
07-28-2005, 03:27 AM
thank you for all replies and especially for Bitmap Font application. I found way for fast text rendering - I use texture generated by that app and then place all my strings to one texcoords/vertex array and then render it with glDrawArrays. this works _much_ faster than drawing each char or/and using display lists. now I can render 30000 chars without any performance problems. this is _much_ better that GLTT or FTGL

GPSnoopy
07-28-2005, 04:28 AM
Here I also use FreeType 2 to generate a texture containing all ASCII chars at startup.

A few technical details:

The texture is divided into 'cells', every cell has the same size, and each cell contain one glyph (~letter). Also, the glyphs are centered inside their cell.

This avoids bleeding at the expense of memory usage.

When drawing the glyphs in OpenGL, the algorithm actually display the whole cell (not just the glyph). The cells are translated to match the correct glyphs position.

This avoids problem that arises with linear and/or linear-with-mipmap filtering at the border of the glyph. Because a glyph is centered inside the cell, the probability that it gets trunkated is remote.

http://users.telenet.be/tfautre/hello_dan1.png
http://users.telenet.be/tfautre/hello_dan2.png
http://users.telenet.be/tfautre/hello_dan3.png

SeskaPeel
07-28-2005, 06:30 AM
Snoopy, you could achieve better visual quality by generating a different texture for a given pixel height. And so, no mipmapping, and cells having different sizes.

But obviously, you'll have a lot more textures if you render chars with different sizes.

pronvit : suprisingly, you should be able to fine tune FTGL to get maximum performance if you're not memory limited. Maybe you could give it a second try.

SeskaPeel.

SeskaPeel
07-28-2005, 06:34 AM
Stephen_H : they implemented a new auto hinter, that renders perfectly ...

SeskaPeel.

pronvit
07-28-2005, 06:59 AM
Originally posted by SeskaPeel:
pronvit : suprisingly, you should be able to fine tune FTGL to get maximum performance if you're not memory limited. Maybe you could give it a second try.I was looking at FTGL code and found that it renders each char with separate GL function call. Then I made simple test - tried to render 10000 quads with one texture using separate GL calls (or using display lists) and performance wasn't acceptable. Only by using arrays I can do this as fast as I need.

In any case, I don't need any other engine now, I have my own :)