Drawing text with freetype and shaders

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;
}  

Just to make sure you are not in the wrong screen coordinate system:
Try drawText(0,0, 1, “Hello world!”);
Normallly, I’d expect you need values between 0 and 1 for x and y.