Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


allocating a texture large enough to hold all font glyphs


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 Vexator   Members   -  Reputation: 138

Like
0Likes
Like

Posted 24 May 2009 - 11:52 AM

i'm loading truetype fonts with freetype in ogl. i store all glyphs in one single texture. i load all the glyphs in small buffers and then fill them in the texture's buffer. example output: so far i'm just guessing the needed texture dimensions, and that's of course not a good idea. but i'm not quite sure how to do it without wasting too much space. my only idea was to loop through all glyphs and save the biggest width and height, multiply that with the number of characters and count to the next power of two; but this results in way to big (and of course always square) textures with a lot of space wasted. any idea how to do this in a smarter way? thank you :)

Sponsor:

#2 Codeka   Members   -  Reputation: 1157

Like
0Likes
Like

Posted 24 May 2009 - 12:12 PM

Well, you've obviously already got code which can layout the glyphs in a texture. My suggestion would be to do a "dry-run" assuming ever-increasing texture sizes (start off with 64x64, then 128x128, etc - you can choose a bunch of sizes which seem appropriate). Then do a dry-run (without actually creating the texture/copying the glyphs; just measuring the sizes) and if you run out of space in the 64x64 dry run, move onto the 128x128. Keep going until you find a texture size that fits.

Another method would be to use a fixed width (say 256) and then use the dry-run method to find the height you need: just keep filling in lines as you go down, when you hit the last character, the height that you're currently at is the minimum height of the texture you'll need.

#3 SiCrane   Moderators   -  Reputation: 9626

Like
0Likes
Like

Posted 24 May 2009 - 01:49 PM

Or you could use an offline tool like BMFont in order to generate your font texture.

#4 Vexator   Members   -  Reputation: 138

Like
0Likes
Like

Posted 24 May 2009 - 11:23 PM

well, that's basically what i had in mind - either doing a dry run or using/writing an external tool. i just thought there has to be a smarter way and i'm just not getting it. i guess i'll go for the dry-run concept, thank you guys!

#5 Dave   Members   -  Reputation: 1520

Like
0Likes
Like

Posted 24 May 2009 - 11:53 PM

If it were me i'd just do a dry run before you create your texture to see how big it needs to be. This sort of stuff is done offline anyways.

#6 loufoque   Banned   -  Reputation: 93

Like
0Likes
Like

Posted 25 May 2009 - 01:33 AM

Putting all Unicode glyphs in a single texture is bloat.

I suggest you use a library that is already capable of doing it right, such as FTGL.

If you insist on doing it yourself, I suggest you read http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1

#7 Endar   Members   -  Reputation: 668

Like
0Likes
Like

Posted 25 May 2009 - 01:42 AM

You could always take a look at some more sophisticated algorithms. How about using multiple textures? ie. you may save space by using a 512x512 and a 128x128 instead of packing it all into 1 texture which could result in a 1024x1024 texture.

Also, how about rotating some of the glyphs? Then in whatever binary you're loading with the glyphs simply mark that one as rotated.

#8 Vexator   Members   -  Reputation: 138

Like
0Likes
Like

Posted 26 May 2009 - 08:02 AM

of course i could simply use a 3rd party library, but i'm doing this to learn :) another problem i have is choosing which characters to store in the texture. as you can see in my first post, i just store the most basic characters so far, no umlauts, no letters with accents etc. how would you do it? or is it an option to have freetype render characters on the fly, i.e. each time the text string is changed?

#9 mattnewport   GDNet+   -  Reputation: 1029

Like
0Likes
Like

Posted 26 May 2009 - 01:59 PM

Most font code I've seen treats the texture as a cache and writes characters into it on demand. For some languages this is pretty much a requirement - there are too many characters in many asian languages to pre-allocate all the characters you might need if you support arbitrary text (e.g. in game chat). To handle running out of space you can either use standard caching schemes for throwing out the least recently used characters or simply reallocate a new texture with more space as needed (might cause a slight frame rate hiccup but should be a pretty infrequent event). If you go with a fixed size texture with a caching scheme you probably want to support repacking all the existing characters/clearing the cache or you may eventually get 'fragmentation' problems when trying to add new characters.

Unless you are targeting very low system specs you should be able to afford to allocate a sufficiently large texture for a worst case scenario without major problems. Even a 1024x1024 8 bit grayscale or DXT compressed texture isn't a huge deal on a modern PC.

#10 loufoque   Banned   -  Reputation: 93

Like
0Likes
Like

Posted 26 May 2009 - 03:38 PM

There are more than one million characters in Unicode. You can't prerender them to a texture.

You need to do the rendering on demand, which involves fairly complicated Unicode stuff, kerning, hinting, antialiasing, etc.
That is why you should really just use an existing library.

You should really go see the link I posted, it explains everything.

#11 samoth   Crossbones+   -  Reputation: 4913

Like
0Likes
Like

Posted 26 May 2009 - 09:04 PM

Another thing that you would maybe want to add to your dry run is make more efficient use of the available texture space by placing the glyphs in a less wasteful layout.

This is basically the same problem that a lightmap packer has to solve, which is usually done with some more or less complicated binary subdivision scheme.
However, you can get it 90% right and a lot easier simply by sorting glyphs by one dimension (for example height) and making the respective "line" only high enough to fit in the biggest glyph in that line. This is not optimal, but close, and it's fast and easy.

#12 Dmytry   Members   -  Reputation: 1148

Like
0Likes
Like

Posted 26 May 2009 - 11:01 PM

Quote:
Original post by Vexator
any idea how to do this in a smarter way? thank you :)

I did it like this. Firstly, I do not insert characters that resolve to same glyph (your [?]) multiple times. I used same layout method: stepping y by max vertical delta.
Secondly, when making a texture (in memory), I keep width constant and double the height every time i run out of space (just like how std::vector grows). Then, when done, I create opengl texture and upload it to card. So that my texture could be 1024x128 for small font or 1024x2048 for large. Alternatively, you could even allocate in chunks and upload chunks with glTexSubImage2D .
I don't see a point in improving packing by maybe 20% by using more complex algorithms, especially if you prefer to only use power of 2 textures anyway.

I also have unicode support as option; for that I use extra part of texture as glyph cache for non-ASCII glyphs, replacing the least recently used glyph. Naturally, I have to allocate same size to all glyphs when using cache, which is somewhat wasteful, but not so much as for ASCII because the non-ASCII characters that I care about are letters in non-latin alphabets, not punctuation.

#13 Cygon   Crossbones+   -  Reputation: 1124

Like
0Likes
Like

Posted 26 May 2009 - 11:37 PM

I use dynamic textures to cache not only glyphs from a single font but from all fonts, as well as GUI skin bitmaps and other things. To find the optimal placements of the bitmaps on the texture, I use a rectangle packing algorithm (description and source).

Whenever a bitmap is looked up, an internal MRU list is updated to keep track of which bitmaps are being used and in which order. Should too many texture switches occur in a frame (typically because characters from a single font got distributed to different dynamic textures due to space constraints), I move the bitmaps in the order of the MRU onto a new dynamic texture.

I've been thinking of using a time budget for the move (so I put the new dynamic texture together bit by bit, copying only as many bitmaps per frame as I can do in, say, 1 ms). Or doing in in a separate thread. But so far, the complete copy did the trick just fine.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS