OpenGL font rendering
Posted
by
DEElekgolo
on Game Development
See other posts from Game Development
or by DEElekgolo
Published on 2011-11-29T04:48:42Z
Indexed on
2011/11/29
10:10 UTC
Read the original article
Hit count: 385
I am trying to make an openGL text rendering class using FreeType. I was originally following this code but it doesn't seem to work out for me. I get nothing reguardless of what parameters I put for Draw().
class Font
{
public:
Font()
{
if (FT_Init_FreeType(&ftLibrary))
{
printf("Could not initialize FreeType library\n");
return;
}
glGenBuffers(1,&iVerts);
}
bool Load(std::string sFont, unsigned int Size = 12.0f)
{
if (FT_New_Face(ftLibrary,sFont.c_str(),0,&ftFace))
{
printf("Could not open font: %s\n",sFont.c_str());
return true;
}
iSize = Size;
FT_Set_Pixel_Sizes(ftFace,0,(int)iSize);
FT_GlyphSlot gGlyph = ftFace->glyph;
//Generating the texture atlas.
//Rather than some amazing rectangular packing method, I'm just going
//to have one long strip of letters with the height being that of the font size.
int width = 0;
int height = 0;
for (int i = 32; i < 128; i++)
{
if (FT_Load_Char(ftFace,i,FT_LOAD_RENDER))
{
printf("Error rendering letter %c for font %s.\n",i,sFont.c_str());
}
width += gGlyph->bitmap.width;
height += std::max(height,gGlyph->bitmap.rows);
}
//Generate the openGL texture
glActiveTexture(GL_TEXTURE0);
//if I texture exists then delete it.
iTexture ? glDeleteBuffers(1,&iTexture):0;
glGenTextures(1,&iTexture);
glBindTexture(GL_TEXTURE_2D,iTexture);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexImage2D(GL_TEXTURE_2D,0,GL_ALPHA,width,height,0,GL_ALPHA,GL_UNSIGNED_BYTE,0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load the glyphs and set the glyph data
int x = 0;
for (int i = 32; i < 128; i++)
{
if (FT_Load_Char(ftFace,i,FT_LOAD_RENDER))
{
//if it cant load the character
continue;
}
//load the glyph map into the texture
glTexSubImage2D(GL_TEXTURE_2D,0,x,0,
gGlyph->bitmap.width,
gGlyph->bitmap.rows,
GL_ALPHA,
GL_UNSIGNED_BYTE,
gGlyph->bitmap.buffer);
//move the "pen" down the strip
x += gGlyph->bitmap.width;
chars[i].ax = (float)(gGlyph->advance.x >> 6);
chars[i].ay = (float)(gGlyph->advance.y >> 6);
chars[i].bw = (float)gGlyph->bitmap.width;
chars[i].bh = (float)gGlyph->bitmap.rows;
chars[i].bl = (float)gGlyph->bitmap_left;
chars[i].bt = (float)gGlyph->bitmap_top;
chars[i].tx = (float)x/width;
}
printf("Loaded font: %s\n",sFont.c_str());
return true;
}
void Draw(std::string sString,Vector2f vPos = Vector2f(0,0),Vector2f vScale = Vector2f(1,1))
{
struct pPoint
{
pPoint()
{
x = y = s = t = 0;
}
pPoint(float a,float b,float c,float d)
{
x = a;
y = b;
s = c;
t = d;
}
float x,y;
float s,t;
};
pPoint* cCoordinates = new pPoint[6*sString.length()];
int n = 0;
for (const char *p = sString.c_str(); *p; p++)
{
float x2 = vPos.x() + chars[*p].bl * vScale.x();
float y2 = -vPos.y() - chars[*p].bt * vScale.y();
float w = chars[*p].bw * vScale.x();
float h = chars[*p].bh * vScale.y();
float x = vPos.x() + chars[*p].ax * vScale.x();
float y = vPos.y() + chars[*p].ay * vScale.y();
//skip characters with no pixels
//still advances though
if (!w || !h)
{
continue;
}
//triangle one
cCoordinates[n++] = pPoint( x2 , -y2 , chars[*p].tx , 0);
cCoordinates[n++] = pPoint( x2+w , -y2 , chars[*p].tx + chars[*p].bw / w , 0);
cCoordinates[n++] = pPoint( x2 , -y2-h , chars[*p].tx , chars[*p].bh / h);
cCoordinates[n++] = pPoint( x2+w , -y2 , chars[*p].tx + chars[*p].bw / w , 0);
cCoordinates[n++] = pPoint( x2 , -y2-h , chars[*p].tx , chars[*p].bh / h);
cCoordinates[n++] = pPoint( x2+w , -y2-h , chars[*p].tx + chars[*p].bw / w , chars[*p].bh / h);
}
glBindBuffer(GL_ARRAY_BUFFER,iVerts);
glBindBuffer(GL_TEXTURE_2D,iTexture);
//Vertices
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,sizeof(pPoint),&cCoordinates[0].x);
//TexCoord 0
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,sizeof(pPoint),&cCoordinates[0].s);
glCullFace(GL_NONE);
glBufferData(GL_ARRAY_BUFFER,6*sString.length(),cCoordinates,GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES,0,n);
glCullFace(GL_BACK);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_TEXTURE_2D,0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
~Font()
{
glDeleteBuffers(1,&iVerts);
glDeleteBuffers(1,&iTexture);
}
private:
unsigned int iSize;
//openGL texture atlas
unsigned int iTexture;
//openGL geometry buffer;
unsigned int iVerts;
FT_Library ftLibrary;
FT_Face ftFace;
struct Character
{
float ax,ay;//Advance
float bw,bh;//bitmap size
float bl,bt;//bitmap left and top
float tx;
} chars[128];
};
© Game Development or respective owner