4
\$\begingroup\$

I have an implementation currently that stores each letter as it's own separate texture, usually only a couple pixels in width and height. So this has some problems as i am unable to do a batch render, i can only batch render the same characters. I am stuck with this format, all i can do is try and process it into something better at runtime. I was thinking of creating a single larger texture from all the little ones instead.

What algorithm can i use to sort the small images into a larger one?

How big can this texture get without losing pixel precision with single floating point precision UV mapping (texture width/height normalization into percent 0.0 to 1.0)?

\$\endgroup\$
  • 2
    \$\begingroup\$ Check out angelcode.com/products/bmfont, which probably solves your problem. \$\endgroup\$ – msell Sep 15 '14 at 6:41
  • \$\begingroup\$ There are several answered question on this site about texture-packing or font-generation tools. It depends what you need? Generate the atlas from a font-file (eg. TTF, OTF) or pack your existing characters (images) into an atlas. Regarding texture size: Here's an answer on stackoverflow that explains floating point precision. I guess you'll be running into memory problems before encountering a precision error ;) \$\endgroup\$ – bummzack Sep 15 '14 at 7:31
  • 1
    \$\begingroup\$ You dont actually need high resolution textures to renter text of any size, see valve's method here or here. \$\endgroup\$ – wondra Sep 15 '14 at 10:17
  • \$\begingroup\$ Just use a texture atlas to pack all characters in the same texture. Add a 1 pixel border each char to avoid filtering artefacts. \$\endgroup\$ – glampert Sep 15 '14 at 13:56
2
\$\begingroup\$

For more efficient storage of font texture data, if you want to go beyond putting it all in one texture you should check out distance field textures.

A popular distance field texture technique was invented at valve which stores the distance from each pixel to the shape (character in your case). This is great for monochromatic images, such as fonts and decals and gives you the ability to zoom in pretty darn far. Its almost a vector graphics technique but its still just sampling textures.

Its even so simple to implement you can do it with an alpha test in fixed function pipelines!

Check this out for more info: http://blog.demofox.org/2014/06/30/distance-field-textures/

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ "The technique was invented at valve" Slow down there, partner. Valve did indeed use them and did indeed publish a nice paper on their use with a few new tricks for upping the quality, but by no means did anyone at Valve invent the concept of a distance field texture. :) \$\endgroup\$ – Sean Middleditch Nov 11 '15 at 6:24
  • \$\begingroup\$ There were similar techniques before but the exact technique I described was invented at valve. If not, have a reference? \$\endgroup\$ – Alan Wolfe Nov 11 '15 at 15:21
  • \$\begingroup\$ The very first page of Green's paper lists prior art. :) valvesoftware.com/publications/2007/… \$\endgroup\$ – Sean Middleditch Nov 12 '15 at 16:12
  • \$\begingroup\$ All related techniques but none were implemented the way the valve paper was. \$\endgroup\$ – Alan Wolfe Nov 12 '15 at 16:18
  • 1
    \$\begingroup\$ Figured out the issue and fixed the first sentence of 2nd paragraph (; \$\endgroup\$ – Alan Wolfe Nov 12 '15 at 16:33
0
\$\begingroup\$

I created this app to build texture atlases for fonts quite a while back https://fontconvert.codeplex.com/

texture size vs pixel preciscion has a lot of answers depending on if you are attempting pixel perfect rendering on a display of known resolution, or if you are going to be using a single font atlas with scaling to get different font sizes.

For pixel perfect rendering you want your texture needs to be sized to fit all the characters needed from the font at the exact correct resolution

For scaled rendering, you normally want to create the font atlas at the largest scale you plan to use the font at to prevent artifacts at full size.

For both these cases the app will help you decide how large a texture you need.

In either case with modern hardware, having large textures isn't all that much of a problem, however, the app is designed to split the font into multiple textures if needed, though you will need to create a shader that takes a set of UV coords for each texture and and blends the resulting pixel from each texture

typically one UV coord will point to a character on its corresponding texture, and all the others will point at a blank area, or one UV coord can be used if you pass some additional info in the vertex data for each character quad specifying which texture to use

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

there 2 way to do it

  1. use bitmap font, as Ascendion say, each character represented as a GL_QUAD. you can just use 1 texture to render many paragraph, with hundred of GL_QUAD.
  2. you can dynamically generate a texture which has text on it. then use this text texture to render. you just need a single GL_QUAD to render a paragraph, but be careful, as the text grow, memory needed to store text texture grow too.

in fact, we use both way to render texts, 1st method, for those text that change frequently(item description, chat log, ...). 2nd method, for those text that fixed during game running(game name, player name, ...).

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

For my font renderer I store all characters in a texture_array, which eliminates the need for atlas mapping and worrying about uv float precision.

For drawing use pointsprites and give each vert only a single attrib for character id, while the vertex shader tracks the spacing and scaling, you could easily adapt it to render multiple lines. Afaik this is the best way to maximally take advantage of gpu for rendering text.

uniform vec2 corner;//ndc
uniform vec2 scale;//ndc
uniform int px;

layout(location=0) in int chin;

flat out int character;
void main(){
    gl_PointSize= px;
    gl_Position= vec4(gl_VertexID, 0., 0., 1.);
    gl_Position.xy*= scale;
    gl_Position.xy+= corner;
    character= chin;
}


uniform sampler2DArray tex;
uniform vec4 coloration;

flat in int character;

out vec4 color;
void main(){
    color= texture(tex, vec3(gl_PointCoord, character))*coloration;
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.