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: 361

Filed under:
|

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

Related posts about opengl

Related posts about fonts