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
#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; glm::ivec2 Size; glm::ivec2 Bearing; GLuint Advance; };
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
#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)
{
F_shader.use();
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(va_font);
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;
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 }
};
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBindBuffer(GL_ARRAY_BUFFER, vb_font);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.Advance >> 6) * scale; }
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
Shader FontRenderer::FontInit()
{
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()
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (GLubyte c = 0; c < 128; c++)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
continue;
}
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
);
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);
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);
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
glRenderLoop()
{
FontRenderer FR;
Shader font_shader = FR.FontInit();
FR.FontSetup();
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.