2D text with Freetype not appearing in 3D application

I wanted to add some 2D text, using Freetype, to a game that I’m developing. The code all seems to be running correctly; however, when I compile and run the application the text simply isn’t rendered. Here is the code I’m using to actually load and render the text:


/*******************************************************************
q
******************************************************************/
#include <iostream>

#include "ogldev_math_3d.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include "text_technique.h"


TextTechnique::TextTechnique(GLuint width, GLuint height)
{
	// Load and configure shader
	if (!Technique::Init()) {
		printf("failed
");
	}

	if (!AddShader(GL_VERTEX_SHADER, "Shaders/text.vs")) {
		printf("failed
");
	}

	if (!AddShader(GL_FRAGMENT_SHADER, "Shaders/text.fs")) {
		printf("failed
");
	}

	if (!Finalize()) {
		printf("failed
");
	}

	m_projectionLocation = GetUniformLocation("projection");
	m_textLocation = GetUniformLocation("text");
	m_colorLocation = GetUniformLocation("textColor");

	orthoInf.r = width;
	orthoInf.l = 0.0f;
	orthoInf.b = 0.0f;
	orthoInf.t = height;
	orthoInf.f = 1.0f;
	orthoInf.n = 1.0f;
	Matrix4f ortho;
	ortho.InitOrthoProjTransform(orthoInf);

	glUniformMatrix4fv(m_projectionLocation, 1, GL_TRUE, (const GLfloat*)ortho.m);
	glUniform1i(m_textLocation, 0);

	// Configure VAO/VBO for texture quads
	glGenVertexArrays(1, &this->VAO);
	glGenBuffers(1, &this->VBO);
	glBindVertexArray(this->VAO);
	glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
	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);
}

void TextTechnique::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;
	printf("library
");
	// 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;
	printf("face
");
	// 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
	printf("unpack
");
	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,
			Vector2i(face->glyph->bitmap.width, face->glyph->bitmap.rows),
			Vector2i(face->glyph->bitmap_left, face->glyph->bitmap_top),
			face->glyph->advance.x
		};
		Characters.insert(std::pair<GLchar, Character>(c, character));
	}
	printf("loop
");
	glBindTexture(GL_TEXTURE_2D, 0);
	// Destroy FreeType once we're finished
	FT_Done_Face(face);
	FT_Done_FreeType(ft);
	printf("done
");
}

void TextTechnique::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, Vector3f color)
{
	// Activate corresponding render state
	glUniform3f(m_colorLocation, color.x, color.y, color.z);
	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;
		GLfloat ypos = y + (this->Characters['H'].Bearing.y - ch.Bearing.y) * scale;

		GLfloat w = ch.Size.x * scale;
		GLfloat h = ch.Size.y * scale;
		// Update VBO for each character
		GLfloat vertices[6][4] = {
			{ xpos,     ypos + h,   0.0, 1.0 },
			{ xpos + w, ypos,       1.0, 0.0 },
			{ xpos,     ypos,       0.0, 0.0 },

			{ xpos,     ypos + h,   0.0, 1.0 },
			{ xpos + w, ypos + h,   1.0, 1.0 },
			{ xpos + w, ypos,       1.0, 0.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);
}

And here is the actual function call in the main program to render the text(the last 2 statements). Note that all calling enable does is select the correct shaders:


void RenderPass()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		m_LightingTech.Enable();

		vector<Matrix4f> Transforms;

		float RunningTime = GetRunningTime();

		m_hero.BoneTransform(RunningTime/2.0, Transforms);
		for (uint i = 0; i < Transforms.size(); i++) {
			m_LightingTech.SetBoneTransform(i, Transforms[i]);
		}
		m_LightingTech.SetEyeWorldPos(m_pGameCamera->GetPos());

		//Begin Shadow stuff
		m_csmFBO.BindForReading();
		Pipeline p;
		p.Orient(m_quad.GetOrientation());

		p.SetCamera(Vector3f(0.0f, 0.0f, 0.0f), m_dirLight.Direction, Vector3f(0.0f, 1.0f, 0.0f));
		for (uint i = 0; i < NUM_CASCADES; i++) {
			p.SetOrthographicProj(m_shadowOrthoProjInfo[i]);
			m_LightingTech.SetLightWVP(i, p.GetWVOrthoPTrans());
		}
		//end shadow stuff

		p.SetCamera(m_pGameCamera->GetPos(), m_pGameCamera->GetTarget(), m_pGameCamera->GetUp());
		p.SetPerspectiveProj(m_persProjInfo);
		m_LightingTech.SetWVP(p.GetWVPTrans());
		m_LightingTech.SetWorldMatrix(p.GetWorldTrans());
		m_pGroundTex->Bind(COLOR_TEXTURE_UNIT);

		m_quad.Render();

		for (int i = 0; i < NumRock_meshES; i++) {
			p.Orient(rock_meshOrientation[i]);
			m_LightingTech.SetWVP(p.GetWVPTrans());
			m_LightingTech.SetWorldMatrix(p.GetWorldTrans());
			rock_mesh.Render();
		}

		m_pHeroTex->Bind(COLOR_TEXTURE_UNIT);

		p.Orient(hero_meshOrientation);
		m_LightingTech.SetWVP(p.GetWVPTrans());
		m_LightingTech.SetWorldMatrix(p.GetWorldTrans());
		m_hero.Render();

		m_pSkyBox->Render();

		m_TextTech->Enable(); //enable the correct shaders
		m_TextTech->RenderText("Hello World!", 0.0f, 0.0f, 10.0f);
	}

Finally, here is the vertex shader:


#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;

uniform mat4 projection;

void main()
{
    gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
    TexCoords = vertex.zw;
} 

And here is the fragment shader:


#version 330 core
in vec2 TexCoords;
out vec4 color;

uniform sampler2D text;
uniform vec3 textColor;

void main()
{    
    vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
    color = vec4(textColor, 1.0) * sampled;
}  

Any help will be greatly appreciated, thanks in advance.