OpenGL + Freetype Text Rendering problems


#1

Hello,
I am working on a project which requires text rendering ( it should be very detailed and it has a lot of zoom etc functionality)
I started with rendering text with freetype,
But the fonts doest render correctly.(see the screenshot)
What could be the issues and how to do it correctly?

First i stored the textures(128)

    ` for (GLubyte c = 0; c < 128; c++)`
      {

          // Load character glyph 
          if (FT_Load_Char(face, c, FT_LOAD_RENDER))
         {
              std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
          continue;
      }
     // Generate texture
      GLuint texture;
      glGenTextures(1, &texture);
      glBindTexture(GL_TEXTURE_2D, texture);
      
     
      // Set texture options
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // make texture of bitmap data
    glTexImage2D(
                  GL_TEXTURE_2D,
                  0,
                  GL_ALPHA,
                  face->glyph->bitmap.width,
                  face->glyph->bitmap.rows,
                  0,
                  GL_ALPHA,
                  GL_UNSIGNED_BYTE,
                  face->glyph->bitmap.buffer
                );

     glGenerateMipmap(GL_TEXTURE_2D);
     
      // Now store character for later use
      Character character = {
        texture, 
        glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
        glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
        glm::ivec2(face->glyph->advance.x,face->glyph->advance.y)

       };

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


   glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Disable byte-alignment restriction
   FT_Done_Face(face);
   FT_Done_FreeType(ft);

Then i used it for rendering text-----

GLuint VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 5, NULL, GL_DYNAMIC_DRAW);
   
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);

     glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void*)( 3 * sizeof(GLfloat))) ;

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);      

  
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(VAO);

    // Iterate through all characters
    std::string::const_iterator c;
    for (c = text.begin(); c != text.end(); c++)
    {

        Character ch = Characters[*c];
        std::cout<<"For=========== "<<*c<<std::endl;
        GLfloat xpos = x + ch.Bearing.x * scale;
        GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;

        GLfloat w = ch.Size.x * scale;
        GLfloat h = ch.Size.y * scale;
        // Update VBO for each character
       
        GLfloat vertices[6][5] = {
            { xpos,     ypos + h, 0.0f,   0.0, 0.0 },            
            { xpos,     ypos,     0.0f,   0.0, 1.0 },
            { xpos + w, ypos,     0.0f,   1.0, 1.0 },

            { xpos,     ypos + h, 0.0f,   0.0, 0.0 },
            { xpos + w, ypos,     0.0f,   1.0, 1.0 },
            { xpos + w, ypos + h, 0.0f,   1.0, 0.0 }           
        };
        

  


        // Render glyph texture over quad
       glBindTexture(GL_TEXTURE_2D, ch.TextureID);
        
        // Update content of VBO memory
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); 
        
        // Render quad
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        // Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        x += (ch.Advance.x >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);

What could be the problems?

i tried printing “OpenGL”


#2

For “O” and “e”, it looks like your texture coordinates run diagonally down the quads.

A more likely explanation is that you haven’t uploaded the image pixels correctly to the OpenGL texture(s) for some of the characters (e.g. told OpenGL that the width was N when the width was really N-1).

If these just happen to be characters that don’t have a width that’s a multiple of 4, I’d suspect that you don’t have your unpack alignment set properly. Try:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

See this FAQ in the wiki for details: Common_Mistakes#Texture_upload_and_pixel_reads


#3

Thank you so much that worked…
It looks good but now with zooming very much it is getting blurred and pixelated edges are visible. How i can resolve this?


#4

That’s magnify with bilinear filtering for you (GL_TEXTURE_MAG_FILTER = GL_LINEAR). That’s what’s built-in for upsampling 2d textures. If you want something better, you have the freedom to implement it. And yes, with these better methods, you can still render the result on the GPU via OpenGL.

A few things you might want to read-up on:

Pixel art scaling algorithms

Vector Textures (aka Signed Distance Field Textures)

  • Here I link to the classic Valve paper from the Half-life 2 days.
  • Another random link to a vector paper with a brief survey of both camps.
  • Another Random link.
  • Websearch “distance field fonts” for instance, such as this project, “distance field textures”, “vector textures”, “vector fonts”, etc.

#5

@Dark_Photon
Thank you so much for all the help and articles. I went through alot of them and they were really helpful. Seems like learning Text rendering is getting more interesting.

Now i am stuck here: Help please: point_down: