2
\$\begingroup\$

I am trying to implement Font Rendering in my OpenGL C++ game.

I read many articles on the subject and got to know different methods, but I am still learning.

Valve has published a paper for Signed Distance Fields and how you can use them with Shaders to generate sharp edges for you text. This has turned out to be the preferred method.

In my project I create all of my characters with Freetype in a loop, bind them to a texture object and reuse them whenever I need a specific character.

I perfectly know that it is not very efficient. Unfortunately, I haven't found a good way to load a bitmap with all the letters and use only single sections. That's why I'm going to use this way for now.

I got everything working (creating the letters, binding the textures and use them for text), but without Signed Distance Fields.

So my Question is how to generate all of my character textures as a Signed Distance Field with the help of Freetype?

This is what my procedure looks like so far:

struct Character {
    GLuint textureID, advance;
    glm::ivec2 size, bearing;
}; 

.

FT_Library ft;
if( FT_Init_FreeType( &ft ) )
{
    throw std::string( "Could not initialize Freetype Library. Abort" );
}

FT_Face t_face;
if( FT_New_Face( ft, t_fontname.c_str(), 0, &t_face ) )
{
    throw std::string( "Could not load " + t_fontname + ". Abort" );
}

// set font size
FT_Set_Pixel_Sizes( t_face, 0, 48 );

// Disable byte-alignment restriction
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

std::map< GLchar, Character > characters;

for( GLubyte c = 0; c < 128; c++ )
{
    // Load character glyph
    if ( FT_Load_Char( t_face, c, FT_LOAD_RENDER ) )
    {
        throw std::string( "Could not load glyph from font. Abort" );
    }

    // Generate texture
    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D
    (
        GL_TEXTURE_2D,
        0,
        GL_RED,
        t_face->glyph->bitmap.width,
        t_face->glyph->bitmap.rows,
        0,
        GL_RED,
        GL_UNSIGNED_BYTE,
        t_face->glyph->bitmap.buffer
    );

    // Set texture options
    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 );

    // Now store character for later use
    Character character =
    {
        tex,
        t_face->glyph->advance.x,
        glm::ivec2( t_face->glyph->bitmap.width, t_face->glyph->bitmap.rows ),
        glm::ivec2( t_face->glyph->bitmap_left, t_face->glyph->bitmap_top )
    };

    characters.insert( std::pair< GLchar, Character >( c, character ) );
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

I already fount this project on github which seems to be a solution. It also depends on Freetype, but to be honest I don't quite understand how the Signed Distance Fields are generated. It might also be too overkill for my intentions.

There are many websites that unfortunately use the old fixed pipeline or are not intended for C++.

\$\endgroup\$
  • 1
    \$\begingroup\$ Check also github.com/rougier/freetype-gl and github.com/raphm/makeglfont \$\endgroup\$ – msell Nov 11 '17 at 15:04
  • \$\begingroup\$ @msell you are right. I already know these sites. I forgot to link them. But I feel like it's a little exaggerated for my project. I'd rather try to implement it myself by using an algorithm or so.. But it's hard to get started \$\endgroup\$ – linux_lover Nov 12 '17 at 14:48
1
\$\begingroup\$

Unfortunately, freetype does not seem to render directly to a distance field as of version 2.9 (check the render modes listed here)

You could calculate the distance from the alpha value of the freetype generated bitmaps using something like the techniques described in the paper "Anti-aliased Euclidean distance transform"

\$\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.