With the help of @Rabbid76 and some web tutorials i have been able to render font in my scene.
The problem i am now facing is that font appears as top aligned instead of bottom aligned.
what i can do is to move the characters down in y position when the letter is not capitol.
1) Would this be the correct way to handle this issue or do we have any standard way of dealing with this.
The function to Load the font and render texture
void MyFont::Load(std::string font, GLuint fontSize)
{// First clear the previously loaded Characters
this->Characters.clear();
// Then initialize and load the FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft)) // All functions return a value different
than 0 whenever an error occurred
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" <<
std::endl;
// Load font as face
FT_Face face;
if (FT_New_Face(ft, font.c_str(), 0, &face))
std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
// Set size to load glyphs as
FT_Set_Pixel_Sizes(face, 0, fontSize);
// Disable byte-alignment restriction
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Then for the first 128 ASCII characters, pre-load/compile their characters and store them
for (GLubyte c = 0; c < 128; c++) // lol see what I did there
{
// 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);
}
The function to map the texture on rectangles.
void MyFont::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat
scale, glm::vec3 color)
{
this->TextShader.Use();
// Activate corresponding render state
glm::mat4 model = glm::rotate(glm::mat4(1.0f), glm::radians(0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::translate(model, glm::vec3(-4.0, -1.0, 0.0));
glm::mat4 view = camera7.GetViewMatrix();
this->TextShader.SetMatrix4("model", model);
this->TextShader.SetMatrix4("view", view);
this->TextShader.SetVector3f("textColor", color);
this->TextShader.SetMatrix4("projection",
glm::perspective(glm::radians(45.0f), (float)800.0 / (float)600.0, 0.1f,
100.0f));
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(this->VAO);
// 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) * 0.1; // Scaling the xpos value
GLfloat ypos = (y + (this->Characters['H'].Bearing.y - ch.Bearing.y) * scale )* 0.1; // Scaling the ypos value
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
w /= 10.f; // Scaling here
h /= 10.f; // scaling here
// Update VBO for each character
GLfloat vertices[6][5] = {
{ xpos, ypos + h, 0.0 , 0.0, 0.0 },
{ xpos + w, ypos, 0.0 , 1.0, 1.0 },
{ xpos, ypos, 0.0 , 0.0, 1.0 },
{ xpos, ypos + h, 0.0, 0.0, 0.0 },
{ xpos + w, ypos + h, 0.0, 1.0, 0.0 },
{ xpos + w, ypos, 0.0, 1.0, 1.0 }
};
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// Update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// Now advance cursors for next glyph
x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (1/64th times 2^6 = 64)
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
The easiest way to compensate that is to flip the y-component of the vertex coordinate and the v-component of the texture coordinate.
Change pos + h
to pos - h
and swap 0.0
and 1.0
:
GLfloat vertices[6][5] = {
// x y z u v
{ xpos, ypos - h, 0.0 , 0.0, 1.0 },
{ xpos + w, ypos, 0.0 , 1.0, 0.0 },
{ xpos, ypos, 0.0 , 0.0, 0.0 },
{ xpos, ypos - h, 0.0, 0.0, 1.0 },
{ xpos + w, ypos - h, 0.0, 1.0, 1.0 },
{ xpos + w, ypos, 0.0, 1.0, 0.0 }
};
Note the base of the text changes from top to bottom in this case.