# Optimizing a Bitmap Font

## Recommended Posts

wforl    169
At the moment im just rendering out each letter via its only shader call, which is obviously not a good way of doing things, and am planning to optimize it. The code at the moment works by, 1. converting the data into a sting 2. loop throught each letter - calculate bitmap UV location - apply position, scaling, and ratio correction - send polgon to effect So im looking at making some sort of spritebatch that allows for a container to be filled up with data to be rendered, but renders it all in one go to be more optimized, or when it is manualy flushed. My plan is that when a letter is added to the spritebatch, i calculate the UV,scale, pos, and ratio correction into one matrix, along with the char, and then pop this into the container. And then when the spritebatch comes to render, i multiply the same polygon vertices by each of the spritbatch data members, so that rendering is done all in one go, with the sprite batch being rendered each frame, and the spritebatch then being renewed each frame, for when the letters chnage, or some affect is applied,
//add to batch call
///////////////////////////////

spritebatchObject t;
t.U = getU(char)
t.V = getV(char)
t.colour = col
t.transform = ( pos,scale,ratio corection etc etc)

spritebatch.pushback(t);

//render entire batch call
/////////////////////////////////

start pass

for(i = 0, i < spritebatch.size(), ++i){
.. etc etc

lockVbuffer squarePoly
//set verts UVs
unlockVbuffer squarePoly

dev->SetStreamSource(squarePoly);
}

end pass


but this is still going to be slow as each letter gets sent to the effect. And then theres the wasteage that the text is getting calculated each frame, when generally its only the UVs that are going to change. So im basically looking for way to create a descent optimzed bitmap font renderer

##### Share on other sites
Gage64    1235
Sorry if I'm missing something, but why do you have to render each letter separately?

Can't you just take the string, create a quad for every letter in it, put the quads in a dynamic VB and render the whole VB in one draw call?

You also don't have to do this every frame for every string, just for the strings that change. In fact, if some of your strings are constant, you can put them in a static VB and never touch the VB.

EDIT: You might also want to take a look here.

##### Share on other sites
Hodgman    51336
Quote:
 Original post by Gage64Can't you just take the string, create a quad for every letter in it, put the quads in a dynamic VB and render the whole VB in one draw call?You also don't have to do this every frame for every string, just for the strings that change. In fact, if some of your strings are constant, you can put them in a static VB and never touch the VB.
Yep, that's how my font renderer works.
Whenever the string is modified, I calculate all the vert/UV coordinates and fill up a VB with a bunch of quads.
Then every frame I just render the VB using the font shader.

##### Share on other sites
wforl    169
So you're creating a new vertex buffer each time the data changes?, and then rendering a triangle strip with the whole string?

Hmm, have you also allowed for +/- padding between the letters?

So do you mean something like

//render current healthstatic int LastHealth = 0;static VertexPT* healthVB = 0;if(LastHealth == player.health)    RenderFont(&healthVB );else{   healthVB ->Release();   calculateNewBuffer(&healthVB , player.health);   lasthealth = health;}

##### Share on other sites
Gage64    1235
Quote:
 Original post by wforlhealthVB ->Release();

Destroying and recreating the VB is expensive and is unnecessary; you can just modify it's contents. If you're using a dynamic VB (as you should for this sort of thing), this can be done in an efficient way. See here for more info.

##### Share on other sites
wforl    169
but i wont know what size to create the buffer until i receive the string. Do you mean just create a buffer thats longer than i'll ever need?

##### Share on other sites
Gage64    1235
Quote:
 Original post by wforlbut i wont know what size to create the buffer until i receive the string. Do you mean just create a buffer thats longer than i'll ever need?

Usually you use a VB to store geometry data (such as the characters in your game). Such a VB is usually large enough to hold thousands of vertices (especially if you put several models in one VB, which is often done to reduce switching between VBs).

I think a string of text needs far less vertices than that. Even if you want to use one VB to render several strings to reduce VB switches, you can reuse the VB's memory as shown in the link I posted.

So to answer your question - yes, I think creating a VB large enough to hold any string is reasonable.