OpenGL ES texture fonts

来源:互联网 发布:用java调用weka j48 编辑:程序博客网 时间:2024/04/30 06:22

http://www.allegro.cc/forums/thread/599388

I would like to implement texture fonts in OpenGL ES. Is it possible to use GL_ALPHA textures? They are more space efficient than GL_RGBA. Is it possible to color the text when using GL_ALPHA textures? How? Could you send a sample code?


OpenGL ES support GL_ALPHA. It's then up to the OpenGL ES driver whether the texture you've supplied in GL_ALPHA form remains so, which will depend on whether your GPU supports GL_ALPHA. I believe that the PowerVR in the iPhone does (and can confirm that the example texture class provided by Apple uploads as GL_ALPHA when you load a suitable PNG or supply data tagged as being of that format), otherwise I'm not very certain.

Colour text using GL_ALPHA in OpenGL ES almost exactly as you would with normal OpenGL. So, for example, set the texture environment mode to 'modulate':

  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Then subsequently use calls to glColor4f (the number of combinations and permutations of glColor is reduced in OpenGL ES) to set the colour of the next string. Alternatively, supply something to glColorPointer (either directly supply data, or use the connected vertex buffer object (VBO) measures) if you want to specify colour per-vertex.

Just on the off chance that you are targetting the iPhone (my guess is that it is currently the most targetted OpenGL ES platform, but I'm fully aware that there are several other OpenGL ES platforms that are viable), note that the implementation of VBOs means that using them doesn't provide anything even close to the speed boost you'd get for switching on a conventional desktop target. There are some minor throughput increases, but definitely if you're starting out then don't worry about them now. The speed difference isn't very great, and you can worry about them later in the day — they're an extension that is easy to patch on to existing code.

EDIT:
Oh! Sample code! If you'll excuse the higgledy-piggledy blend of C++ and Objective-C:

1#include "Text.h"2 3CRotoText *TextWriter;4Texture2D *TextSheet;5 6#define NUM_GLYPHS 447 8struct Glyph9{10CVertexArray *Vertices;11CTexCoordArray *TexCoords;12float Width;13} Glyphs[NUM_GLYPHS];14 15CRotoText::CRotoText()16{17TextSheet = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"font.png"]];18[TextSheet Activate];19glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);20glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);21 22int Coords[NUM_GLYPHS][4] =23{24/* numbers 0 - 9 */25{1, 14, 4, 18},26{6, 14, 8, 18},27{10, 14, 13, 18},28{15, 14, 18, 18},29{20, 14, 23, 18},30{25, 14, 28, 18},31{30, 14, 33, 18},32{35, 14, 38, 18},33{40, 14, 43, 18},34{45, 14, 48, 18},35 36/* letters a - m */37{1, 1, 4, 5},38{6, 1, 9, 5},39{11, 1, 14, 5},40{16, 1, 19, 5},41{21, 1, 23, 5},42{25, 1, 27, 5},43{29, 1, 32, 5},44{34, 1, 37, 5},45{40, 1, 40, 5},46{43, 1, 46, 5},47{48, 1, 51, 5},48{53, 1, 55, 5},49{57, 1, 61, 5},50 51/* letters n - z */52{1, 7, 5, 11},53{7, 7, 10, 11},54{12, 7, 15, 11},55{17, 7, 20, 12},56{22, 7, 25, 11},57{27, 7, 30, 11},58{32, 7, 34, 11},59{36, 7, 39, 11},60{41, 7, 45, 11},61{50, 14, 54, 18},62{47, 7, 51, 11},63{53, 7, 57, 11},64{59, 7, 61, 11},65 66/* dot, semi-colon, space, exclamation mark, question mark, apostrophe */67{56, 14, 56, 18},68{58, 14, 58, 18},69{1, 20, 3, 24},70{60, 14, 60, 18},71{58, 20, 60, 24},72{54, 20, 54, 21},73{50, 20, 52, 22},74{46, 20, 47, 25},75};76int c = NUM_GLYPHS;77while(c--)78{79GLfloat Positions[8] = {0, 0}, TexCoords[8];80 81Positions[0] =82Positions[2] = (GLfloat)(1+Coords[c][2] - Coords[c][0]) / 64.0;83Positions[3] =84Positions[7] = 0;85 86Positions[4] =87Positions[6] = 0;88Positions[1] =89Positions[5] = -(GLfloat)(1+Coords[c][3] - Coords[c][1]) / 32.0;90 91TexCoords[4] = 92TexCoords[6] = ((GLfloat)Coords[c][0] ) / 64.0;93TexCoords[3] = 94TexCoords[7] = ((GLfloat)Coords[c][1] ) / 32.0;95 96TexCoords[0] = 97TexCoords[2] = ((GLfloat)Coords[c][2] + 1) / 64.0;98TexCoords[1] = 99TexCoords[5] = ((GLfloat)Coords[c][3] + 1) / 32.0;100 101Glyphs[c].Vertices = new CVertexArray(2, GL_FLOAT, Positions, 4);102Glyphs[c].TexCoords = new CTexCoordArray(2, GL_FLOAT, TexCoords, 4);103Glyphs[c].Width = Positions[0] + 1.0/64.0;104}105}106 107CRotoText::~CRotoText()108{109[TextSheet release];110}111 112int CRotoText::GetGlyph(char t)113{114if(t >= 48 && t < 58) return t - 48;115t = toupper(t);116if(t >= 65 && t < 91) return t - 55;117 118switch(t)119{120default: return -1;121case '.': return 36;122case ':': return 37;123case ' ': return 38;124case '!': return 39;125case '?': return 40;126case '/'': return 41;127case '-': return 42;128case ',': return 43;129}130}131 132 133void CRotoText::WriteString(char *fmt, ...)134{135char Buffer[2048];136va_list varg;137 138va_start(varg, fmt);139vsnprintf(Buffer, 2048, fmt, varg);140va_end(varg);141 142char *P = Buffer;143[TextSheet Activate];144glPushMatrix();145glScalef(1, 0.5, 1);146while(*P)147{148int ToPrint = GetGlyph(*P);149 150if(ToPrint >= 0)151{152Glyphs[ToPrint].Vertices->Enable();153Glyphs[ToPrint].TexCoords->Enable();154glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);155glTranslatef(Glyphs[ToPrint].Width, 0, 0);156}157P++;158}159glPopMatrix();160}161 162float CRotoText::StringWidth(char *fmt, ...)163{164char Buffer[2048];165float Width = 0;166va_list varg;167 168va_start(varg, fmt);169vsnprintf(Buffer, 2048, fmt, varg);170va_end(varg);171 172char *P = Buffer;173while(*P)174{175int ToPrint = GetGlyph(*P);176 177if(ToPrint >= 0)178Width += Glyphs[ToPrint].Width;179P++;180}181return Width;182}183 184void CRotoText::SetScale(float scale)185{186glScalef((float)scale * (128.0/480.0), (float)scale * (128.0/480.0), 1);187}

That code is hardcoded to the particular font bitmap I was using, as shown by the way that it doesn't even use ASCII for its internal table. CVertexArray and CTexCoordArray are my own little classes for storing stuff that will later be passed to glVertexArray and glTexCoordArray (via a VBO, but whatever), these two lines:

  TextSheet = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"font.png"]];  [TextSheet Activate];

Just load and then activate a texture from the file 'font.png' using Apple's example texture class. They're Objective-C, which is why they might look slightly odd.

The text ends up being output in whatever colour was last set with glColor4f. The SetScale function is specific to the projection matrix I have set up elsewhere and the size of the font. You'll notice that each glyph is a very small number of pixels indeed (typically three or four across by five high), so I needed to be very specific about ensuring that texels map exactly to pixels, or things would look really blurry.