Hi,
I’m trying to add freetype text to my running program. The code below was adapted from EdoardoLuciani. No text is shown, though.
Could you help me to find the bug, please?
- DELL XPS
- GPU 1050
- OpenGL 4.6
- Win32
- Language C
// Main program
initText();
// Drawing loop
...
{
...
drawText(10, 300, 1, "Hello world!");
...
}
void initText()
{
// Extract glyphs textures
//
glUseProgram(textShader);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, "arial.ttf", 0, &face);
FT_Set_Pixel_Sizes(face, 0, 48);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int c = 0; c < 128; c++)
{
FT_Load_Char(face, c, FT_LOAD_RENDER);
//
GLuint texture;
glCreateTextures(GL_TEXTURE_2D,1, &texture);
glTextureStorage2D(texture, 1, GL_R8, face->glyph->bitmap.width, face->glyph->bitmap.rows);
glTextureSubImage2D(texture, 0, 0, 0, face->glyph->bitmap.width, face->glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
//
glBindTexture(GL_TEXTURE_2D, texture);
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);
//
// Test if texture was loaded
//
GLint isTexResident;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_RESIDENT, &isTexResident);
if(isTexResident == GL_FALSE)
{
printf("texture %d not resident.\n", texture);
fflush(stdout);
}
glBindTexture(GL_TEXTURE_2D, 0);
//
// Save glyph
//
Character ch;
ch.TextureID = texture;
ch.Bearing[0] = face->glyph->bitmap.width;
ch.Bearing[1] = face->glyph->bitmap.rows;
ch.Size[0] = face->glyph->bitmap_left;
ch.Size[1] = face->glyph->bitmap_top;
ch.Advance = face->glyph->advance.x;
characters[c] = ch;
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
//
// Create VAO
//
glCreateVertexArrays(1, &textVAO);
glBindVertexArray(textVAO);
//
// Create VBO
//
glCreateBuffers(1, &VBO);
glNamedBufferStorage(VBO, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayVertexBuffer(textVAO, 0, VBO, 0, sizeof(GLfloat) * 4);
glVertexArrayAttribFormat(textVAO, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(textVAO, 0, 0);
glEnableVertexArrayAttrib(textVAO, 0);
//
// Send color to fragment shader
//
glUniform3f(6, 0.88f, 0.59f, 0.07f);
}
void drawText(float x, float y, float scale, char *text)
{
glEnable(GL_CULL_FACE);
glUseProgram(textShader);
//
// Draw each character
//
char *c = text;
while(*c != 0)
{
Character ch = characters[(int)*c];
GLfloat xpos = x + ch.Bearing[0] * scale;
GLfloat ypos = y - (ch.Size[1] - ch.Bearing[1]) * scale;
//
GLfloat w = ch.Size[0] * scale;
GLfloat h = ch.Size[1] * scale;
//
// Update VBO for each character
//
GLfloat vertices[6*4] =
{
xpos, ypos + h, 0.0f, 0.0f ,
xpos, ypos, 0.0f, 1.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos, ypos + h, 0.0f, 0.0f ,
xpos + w, ypos, 1.0f, 1.0f ,
xpos + w, ypos + h, 1.0f, 0.0f
};
glNamedBufferSubData(VBO, 0, sizeof(GLfloat)*6*4, vertices);
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBindVertexArray(textVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.Advance >> 6) * scale;
c++;
}
glDisable(GL_CULL_FACE);
}
The fragnment shader:
#version 460 core
in vec2 TexCoords;
out vec4 color;
layout (binding = 0) uniform sampler2D text;
layout (location = 6) uniform vec3 textColor;
void main()
{
color = vec4(textColor, 1.0) * texture(text, TexCoords).r;
}
The vertex shader:
#version 460 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
layout (location = 1) uniform mat4 projection;
out vec2 TexCoords;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}