Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have to display text. For that, I am trying to follow this[1] tutorial to display the text.

As mentioned in the tutorial, I've linked the libraries and there seem to be no error in linking of the library.
So here is the structure of my application. The entry point of my project is *radar.cpp*. And for rendering the text, I have created a FontRenderer.h with a corresponding FontRenderer.cpp file as described below.

1. FontRenderer.h
C++
#include <ft2build.h>
#include "graphics.h"
#include <iostream>
#include <map>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shader_s.h"

#include FT_FREETYPE_H

struct Character {
    GLuint TextureID;       // ID handle of the glyph texture
    glm::ivec2 Size;        // Size of glyph
    glm::ivec2 Bearing;     // Offset from baseline to left/top of glyph
    GLuint Advance;         // Horizontal offset to advance to next glyph
};

class FontRenderer
{
private:
    FT_Library ft;
    FT_Face face;
public:
    void RenderText(Shader fshader, std::string text, GLfloat x, GLfloat y, GLfloat scale, GLuint va_font, GLuint vb_font);
    Shader FontInit();
    void FontSetup();
};
2. FontRenderer.cpp
C++
#include"FontRenderer.h"
#include<glad/glad.h>
#include <GLFW/glfw3.h>

std::map<GLchar, Character> Characters;

void FontRenderer::RenderText( Shader F_shader, std::string text, GLfloat x, GLfloat y, GLfloat scale, GLuint va_font, GLuint vb_font)
{
    // Binding vertex array for font class
    F_shader.use();
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(va_font);

    // Iterate through all characters
    std::string::const_iterator c;
    for (c = text.begin(); c != text.end(); c++)
        {
        Character ch = Characters[*c];

        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 vb_font for each character
        GLfloat vertices[6][4] = {
            { xpos,     ypos + h,   0.0, 0.0 },
            { xpos,     ypos,       0.0, 1.0 },
            { xpos + w, ypos,       1.0, 1.0 },

            { xpos,     ypos + h,   0.0, 0.0 },
            { xpos + w, ypos,       1.0, 1.0 },
            { xpos + w, ypos + h,   1.0, 0.0 }
        };
        // Render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D, ch.TextureID);
        // Update content of vb_font memory
        glBindBuffer(GL_ARRAY_BUFFER, vb_font);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
        //Unbinding the currently bound buffer
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        // Render quad
        glDrawArrays(GL_TRIANGLES, 0, 6);
        // Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

Shader FontRenderer::FontInit()
{
    // Compile and setup the shader
    Shader shader("shaders/text.vs", "shaders/text.frag");
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(800), 0.0f, static_cast<GLfloat>(600));
    shader.use();
    glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

    if (FT_Init_FreeType(&ft))
    {
        std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
    }

    if (FT_New_Face(ft, "Fonts/dataUnifon.ttf", 0, &face))
    {
        std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
    }
    FT_Set_Pixel_Sizes(face, 0, 48);
    printf("FreeType Initialization successfull\n");

    return shader;
}

void FontRenderer::FontSetup()
{
    // Disable byte-alignment restriction
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // Load first 128 characters of ASCII set
    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);
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RED,
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RED,
            GL_UNSIGNED_BYTE,
            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 = {
            texture,
            glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
            glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
            face->glyph->advance.x
        };
        Characters.insert(std::pair<GLchar, Character>(c, character));
    }
    glBindTexture(GL_TEXTURE_2D, 0);

    // Destroy FreeType once we're finished
    FT_Done_Face(face);
    FT_Done_FreeType(ft);
}
I have one daddy function to manage all the OpenGL rendering called glRenderLoop() defined in some other graphics.cpp file (from where I was calling different functions to render multiple objects on the screen)

This is how glRenderLoop() looks like
C++
glRenderLoop()
{
        FontRenderer FR;

    // Initialize the FreeType fonts
    Shader font_shader = FR.FontInit();
    FR.FontSetup();

    // Configure va_font/vb_font for texture quads
    GLuint va_font, vb_font;
    glGenVertexArrays(1, &va_font);
    glGenBuffers(1, &vb_font);
    glBindVertexArray(va_font);
    glBindBuffer(GL_ARRAY_BUFFER, vb_font);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window))
    {
        glViewport(0, 0, 200, 60);
        glUniform4f(location, 0.9f, 0.9f, 0.0f, 1.0f);

        FR.RenderText(font_shader, "This is sample text", 25.0f, 25.0f, 1.0f, va_font, vb_font);
        FR.RenderText(font_shader, "(C) LearnOpenGL.com", 540.0f, 570.0f, 0.5f, va_font, vb_font);
    glFlush();
    glSwapBuffer(windows);

    }
}

The main() function has just function calls to this glRenderLoop() function which is defined in graphics.cpp

Link to [shader_s.h][2].
I've also made the necessary changes in shader_s.h like using lower case 'u' in use() function, changing 'ID' to 'Program'.

Still, after all this, there is no text rendering on the screen.

What am I doing wrong? :(

[1]: https://learnopengl.com/In-Practice/Text-Rendering
[2]: https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/shader_s.h

What I have tried:

I've tried disabling all other rendering at the moment for debugging purpose, so just freetype is the only remaining active graphics rendering file.
But still no result is achieved so far. Screen appears absolutely blank

However, when I render other elements (Like rendering squares/circles/ triangles) everything is working.
I want to add text as well.
Posted
Updated 30-Oct-18 18:33pm
v2
Comments
Rick York 19-Sep-18 16:56pm    
I don't have a good answer for you. What I usually do when my rendering code isn't working is I add some trace statements to see what data it is trying to draw. Either that, or use the debugger to look at things but I usually have so much being drawn that the debugger is rather unwieldy for this so I output the data using trace statements or something similar.
simarmannsingh 19-Sep-18 17:03pm    
Thanks Rick For your prompt response. I am a beginner in OpenGL. So what I've also tried is adding print statements at the end of each function I am calling, just to track where things are not working or any exception is being raised. Problem is, everything seems to appear fine, all print statements are being executed. I've tried using debugger to check the values of each variable. After all this, code still doesn't produce any text that I am trying to print. Is there any other way to display text as well, apart from using Freetype or using Bitmaps?

Just one point I see in your code, that is your projection in the FontRenderer is bigger than your viewport. I also suggest you should init VAO, VBO inside the FontRenderer instead via the variable. I also use the freetype for render the text and it is fine. I will send you the link demo if you still can not draw the text.
 
Share this answer
 
Comments
Dickens A S 21-Nov-19 12:56pm    
Hi @Seal2002 may I have the link for the fixed code
Seal2002 22-Nov-19 9:06am    
Hi, here you are
https://github.com/seal2002/AdvancedOpenGL
Member 15987572 27-Apr-23 4:04am    
this link don't have code. saying ERROR 404. please will you upload project again
Seal2002 23-Aug-23 9:37am    
Hi,
I deleted it by mistake and I didn't work on OpenGL anymore. I'm sorry about that. You can search on the LearnOpenGL page, I recall my code based on Text rendering article.
Thanks @Seal2002. I really appreciate it. It is working fine now. :)
 
Share this answer
 
Comments
CHill60 31-Oct-18 8:16am    
Seal2002 will not know that you responded .... if you want to comment on a post use the "Have a Question or Comment?" link next to it
Seal2002 5-Nov-18 2:04am    
Yes, I have not noticed the answer until I comeback to this post.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900