SDL_ttf slowdown

Hi,

we are using SDL_ttf for font rendering in our game. But the rendering
slows the game down a lot. We have to transfer the SDL_Surface to an
opengl texture.

We already implemented a hash cache - but nevertheless it is slow. Can
you give me any hints or code examples on how to use SDL_ttf in a
fast(er) way.

Best regards
Martin–

http://www.ufoai.net
http://www.lanadminsystem.de
UIN: 68877410
Jabber: @Martin_Gerhardy
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060824/092da8cb/attachment.pgp

Hi,

I do this by setting up 256 textures and 256 display lists, one for
every character. Each display list renders a GL_QUAD and does a
glTranslate() on the current modelview matrix, so the next character
will be placed correctly. Then all you have to do is, set the modelview
matrix once for each string you want to render and call glListBase()
followed by glCallLists(), where you can put the string directly into
glCallLists() like glCallLists(strlen(x), GL_UNSIGNED_BYTE, x).

The major disadvantage of this method is, that small text might look
strange, if the texels don’t match to screen pixels. There’s a bit more
work to do, to achieve this exact mapping.
In addition, the preparation (256 textures and display lists) can not be
done in realtime, so you have a limited number of font sizes in the
game. Of course you can resize by simply glScale() the modelview matrix,
but this leads (in most cases) to blurred looking characters.

Matthias

Martin Gerhardy schrieb:> Hi,

we are using SDL_ttf for font rendering in our game. But the rendering
slows the game down a lot. We have to transfer the SDL_Surface to an
opengl texture.

We already implemented a hash cache - but nevertheless it is slow. Can
you give me any hints or code examples on how to use SDL_ttf in a
fast(er) way.

Best regards
Martin



SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

we are using SDL_ttf for font rendering in our game. But the rendering
slows the game down a lot. We have to transfer the SDL_Surface to an
opengl texture.

We already implemented a hash cache - but nevertheless it is slow. Can
you give me any hints or code examples on how to use SDL_ttf in a
fast(er) way.

We do that too, and it isn’t slow - if I understood correctly, you
render once and keep the texture around as long as the text is valid,
right? For text that doesn’t change often, that should work perfectly.

For text that does change often (such as a Score counter), what I did
(just in case, not because I found any performance issue) was having
separate textures for each digit. But this was a special case, the
general case worked good enough most of the time.

I’m curious, do you have any figures about what you describe as “slow”?

--Gabriel________________________________________________________________________

Gabriel Gambetta
Mystery Studio - http://www.mysterystudio.com
Gabriel on Graphics - http://gabrielongraphics.blogspot.com

we are using SDL_ttf for font rendering in our game. But the rendering
slows the game down a lot. We have to transfer the SDL_Surface to an
opengl texture.

We already implemented a hash cache - but nevertheless it is slow. Can
you give me any hints or code examples on how to use SDL_ttf in a
fast(er) way.

The way I do it is much like using bitmap fonts. At load time, glyphs
are pre-rendered for each font size/style/color combo that’s used. The
glyphs are first drawn to an SDL surface which is converted to a
texture. After that, strings are drawn one letter at a time in a loop
using an array that maps ASCII values directly to the corresponding
glyph textures. So it’s like generating bitmap fonts at runtime. It’s
VERY fast because it doesn’t require any re-building of surfaces (and in
your case also converting them to OpenGL textures) when text changes.

we are using SDL_ttf for font rendering in our game. But the rendering
slows the game down a lot. We have to transfer the SDL_Surface to an
opengl texture.

We already implemented a hash cache - but nevertheless it is slow. Can
you give me any hints or code examples on how to use SDL_ttf in a
fast(er) way.

The way I do it is much like using bitmap fonts. At load time, glyphs
are pre-rendered for each font size/style/color combo that’s used. The
glyphs are first drawn to an SDL surface which is converted to a
texture. After that, strings are drawn one letter at a time in a loop
using an array that maps ASCII values directly to the corresponding
glyph textures. So it’s like generating bitmap fonts at runtime. It’s
VERY fast because it doesn’t require any re-building of surfaces (and in
your case also converting them to OpenGL textures) when text changes.

Yeah - but do you handle line breaks and such things - you have to run
the string once before to get this data - or am i wrong? That’s the way
we used it in ufo:ai before we switched to sdl_ttf (quake2 engine - used
bitmaps fonts but lacks i18n possibilities)Am Donnerstag, den 24.08.2006, 13:20 -0400 schrieb Ilya Olevsky:


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


http://www.ufoai.net
http://www.lanadminsystem.de
UIN: 68877410
Jabber: @Martin_Gerhardy
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060824/e2e46b1e/attachment.pgp

Yeah - but do you handle line breaks and such things - you have to run
the string once before to get this data - or am i wrong? That’s the way
we used it in ufo:ai before we switched to sdl_ttf (quake2 engine - used
bitmaps fonts but lacks i18n possibilities)

It’s assumed there are no line breaks or anything like that. The system
doesn’t handle formatting, alignment, or multi-line text. These things
are done at a higher level by the GUI which then draws strings one unit
at a time. The smallest unit is a Text widget which is the only thing
that can contain or draw text. There’s also a MultiLineText widget that
contains multiple Text widgets (one per line). It calculates how much
text can exist per line based on the string width, and also handles
alignment.

We do that too, and it isn’t slow - if I understood correctly, you
render once and keep the texture around as long as the text is valid,
right? For text that doesn’t change often, that should work perfectly.

Yep, that should be fine if text doesn’t change.

For text that does change often (such as a Score counter), what I did
(just in case, not because I found any performance issue) was having
separate textures for each digit. But this was a special case, the
general case worked good enough most of the time.

A simple example where text changes a lot is a ListBox. When it’s
scrolled, all the visible rows change. You then have to rebuild all the
surfaces and convert them to textures. Taking this a step further,
imagine that each row in the list box consists of 6 columns. It’s not
much fun to rebuild 36 surfaces (6 rows, 6 columns) and convert them to
textures in real time. :slight_smile: I’m not making this up by the way, this is
what I had to deal with in my current game.

Hi,

I have large graphic files with multiple images in (all the same size, thankfully) as frames of animation. How do I extract them to single surfaces? Do I load the image as normal then “grab” sections with x&y coords (if this is possible, what functions do I call?).

Hope someone can help!

Thanks
Ed---------------------------------
All new Yahoo! Mail “The new Interface is stunning in its simplicity and ease of use.” - PC Magazine

Hello !

I have large graphic files with multiple images in (all the same size,
thankfully) as frames of animation. How do I extract them to single
surfaces? Do I load the image as normal then “grab” sections with x&y
coords (if this is possible, what functions do I call?).

Hope someone can help!

Look at :

bool Load_Tiles (char *Filename, Tiles **TILES_main,
int Tile_Size_X, int Tile_Size_Y)
{
bool status = false;

SDL_Surface *temp	= NULL;

SDL_Rect	tile_rect;

Uint32 index_tile = 0, index_x = 0, index_y = 0;
Uint32 max_nr_tiles = 0, max_nr_tiles_x = 0, max_nr_tiles_y = 0;
Uint32 r_mask = 0, g_mask = 0, b_mask = 0, a_mask = 0;

if ( (*TILES_main) != NULL )    			return status;
if ( strlen (Filename) == 0 )   			return status;
if ( (Tile_Size_X == 0) || (Tile_Size_Y == 0) )	return status;

#if SDL_BYTEORDER == SDL_BIGENDIAN
r_mask = 0xff000000;
g_mask = 0x00ff0000;
b_mask = 0x0000ff00;
a_mask = 0x000000ff;
#else
r_mask = 0x000000ff;
g_mask = 0x0000ff00;
b_mask = 0x00ff0000;
a_mask = 0xff000000;
#endif

temp    = SDL_LoadBMP (Filename);
if (! temp) return status;

if ( (! temp -> w) || (! temp -> h) ) return status;

index_tile = 1;

max_nr_tiles_x = (Uint32) ((temp -> w)    / Tile_Size_X);
max_nr_tiles_y = (Uint32) ((temp -> h)    / Tile_Size_Y);

if ( ((temp -> w) % Tile_Size_X) > 0 )
{
max_nr_tiles_x ++;
}

if ( ((temp -> h) % Tile_Size_Y) > 0 )
{
max_nr_tiles_y ++;
}

max_nr_tiles  = max_nr_tiles_x * max_nr_tiles_y;
max_nr_tiles ++;

(*TILES_main)		    = new Tiles;
(*TILES_main) -> Nr_Tiles	    = max_nr_tiles;

(*TILES_main) -> Tile_Size_X    = Tile_Size_X;
(*TILES_main) -> Tile_Size_Y    = Tile_Size_Y;

(*TILES_main) -> Nr_Tiles_X	    = max_nr_tiles_x;
(*TILES_main) -> Nr_Tiles_Y	    = max_nr_tiles_y;

(*TILES_main) -> Orig_Width	    = temp -> w;
(*TILES_main) -> Orig_Height    = temp -> h;

(*TILES_main) -> Tiles	    = new SDL_Surface *[max_nr_tiles];

(*TILES_main) -> Tiles  [0]	    = NULL;

for (index_y = 0;
    index_y < (temp -> h);
	index_y = index_y + ((*TILES_main) -> Tile_Size_Y))
{
for (index_x = 0;
	index_x < (temp -> w);
	    index_x = index_x + ((*TILES_main) -> Tile_Size_X))
{
    (*TILES_main) -> Tiles [index_tile] =
	SDL_CreateRGBSurface (	SDL_SWSURFACE,
				(*TILES_main) -> Tile_Size_X,
				(*TILES_main) -> Tile_Size_Y,
				32,
				r_mask,
				g_mask,
				b_mask,
				a_mask				);

    tile_rect.x = index_x;
    tile_rect.y = index_y;
    tile_rect.w = (*TILES_main) -> Tile_Size_X;
    tile_rect.h = (*TILES_main) -> Tile_Size_Y;

    SDL_BlitSurface (	temp, & tile_rect,
			(*TILES_main) -> Tiles [index_tile], NULL);

    index_tile ++;
}
}

SDL_FreeSurface (temp);

status = true;

return status;

}

bool Delete_Tiles (Tiles **TILES_main)
{
bool status = false;

Uint32 index_tile	= 0;

if ( (*TILES_main) == NULL )    return status;

for (index_tile = 0;
    index_tile < (*TILES_main) -> Nr_Tiles;
				    index_tile ++)
{
if ( (*TILES_main) -> Tiles [index_tile] != NULL )
{
    SDL_FreeSurface ( (*TILES_main) -> Tiles [index_tile] );
    (*TILES_main) -> Tiles [index_tile] = NULL;
}
}

delete[]	    (*TILES_main)   -> Tiles;
delete	    (*TILES_main);
(*TILES_main)		    = NULL;

status = true;

return status;

}

CU