I am trying to use freetype with OpenGL. I first tried to write my stuff and as it didn't work I just download a code that works well from this tutorial . As I said it works well but the projection are different than what I want. In the tutorial we have this:
glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), 0.0f, static_cast<GLfloat>(HEIGHT));
I changet with this
glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), 0.0f, static_cast<GLfloat>(HEIGHT), -1.0f, 1.0f);
and it still works good. but what I want is origine at the top-left instead of buttom-left so I use this:
glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), static_cast<GLfloat>(HEIGHT),0.0f, -1.0f, 1.0f);
and now it doesn't work anymore, I have no text on screen. other object a correctly rendered except text. Notice that with the 2 previous projections I got text but other objects were present but with upside-down (normal).
my question is why if I draw a text at (0,0) expecting to see it at the top left I have nothing at all. but with other projection I have it at bottom- left as expected?
I could just keep the projection and move one but I really want to understand why it is not working.
NB: I tried to see the result of projection * Position. let say P1 is ortho with 0 on to and P2 orhto with 0 at bottom.
for x,y = (92.8000, 99.7000) I got:
P1 * (x, y, 0.0, 1.0) = [ 0.2320 0.3323 0.0000 -192.5000]
P2 * (x, y, 0.0, 1.0) = [ 0.2320 -0.3323 0.0000 6.9000]
as expected y1 = - y2.
as requested by @vu1p3n0x code for textrender. but it is in the first link
void RenderText(Shader &shader, std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color)
{
shader.Use();
glUniform3f(glGetUniformLocation(shader.Program, "textColor"), color.x, color.y, color.z);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
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 }
};
// 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);
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);
}
The isssue is the Face Culling:
You have enabled face culling and the vertices of the text primitives are in counterclockwise orientation:
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 }
};
If the projection matrix is
glm::mat4 projection = glm::ortho(
0.0f, static_cast<GLfloat>(WIDTH),
0.0f, static_cast<GLfloat>(HEIGHT));
then the faces are not culled, because by default backfaces are culled (see glCullFace
)
and the winding order is counterclockwise (see glFrontFace
).
When you do
glm::mat4 projection = glm::ortho(
0.0f, static_cast<GLfloat>(WIDTH),
static_cast<GLfloat>(HEIGHT), 0.0f);
then the y axis of the viespace is flipped and the winding order of the primitives turns form counterclockwise to clockwise, by the transformation with the orthographic projection matrix in the vertex shader.
Change the winding order which defines the front-facing polygons by glFrontFace(GL_CW)
, to solve the issue:
glCullFace( GL_BACK ); // that is default
glFrontFace( GL_CW ); // that is NOT default
glEnable(GL_CULL_FACE);
Of course you can alternatively change the winding order of the vertices (and flip the y axis of the texture coordinates):
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 }
};