I am trying to add freetype text rendering on top of a 3d rendering library/context with GLES/2 using glut.
They work ok as separate, but when I initialize the 3D rendering context and then add the font rendering function in the glut display loop, I get no errors but no text is displayed. I am currently testing it with Emscripten/WebGL.
This is the freetype text rendering function and it’s also using shaders/glUseProgram to display the text
const char *p;
FT_GlyphSlot g = face->glyph;
/* Create a texture that will be used to hold one "glyph" */
GLuint tex;
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_tex, 0);
/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Set up the VBO for our vertex data */
glEnableVertexAttribArray(attribute_coord);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(attribute_coord, 4, GL_FLOAT, GL_FALSE, 0, 0);
/* Loop through all characters */
for (p = text; *p; p++) {
/* Try to load and render the character */
if (FT_Load_Char(face, *p, FT_LOAD_RENDER))
continue;
/* Upload the "bitmap", which contains an 8-bit grayscale image, as an alpha texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
/* Calculate the vertex and texture coordinates */
float x2 = x + g->bitmap_left * sx;
float y2 = -y - g->bitmap_top * sy;
float w = g->bitmap.width * sx;
float h = g->bitmap.rows * sy;
point box[4] = {
{x2, -y2, 0, 0},
{x2 + w, -y2, 1, 0},
{x2, -y2 - h, 0, 1},
{x2 + w, -y2 - h, 1, 1},
};
/* Draw the character on the screen */
glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* Advance the cursor to the start of the next character */
x += (g->advance.x >> 6) * sx;
y += (g->advance.y >> 6) * sy;
}
glDisableVertexAttribArray(attribute_coord);
glDeleteTextures(1, &tex);
and this is the init function for the 3D context/engine:
GLuint ambient_vert[9][2];
GLuint ambient_frag[9][2];
int compiled, linked;
for (int f=0; f<=1; f++){
for (int l=0;l<=8;l++){
for (int t=0;t<=8;t++){
shaders[l][t][f].ambient_program=glCreateProgram();
}
}
for (int l=0;l<=8;l++){
ambient_vert[l][f]=glCreateShader(GL_VERTEX_SHADER);
const char* vshader[]={GLES2_Shader::version, GLES2_Shader::vert_flags[l], GLES2_Shader::fog_flags[f], GLES2_Shader::vert_shader};
glShaderSource(ambient_vert[l][f],4, (const GLchar**)&vshader, 0);
glCompileShader(ambient_vert[l][f]);
glGetShaderiv(ambient_vert[l][f],GL_COMPILE_STATUS, &compiled);
}
for (int t=0;t<=8;t++){
ambient_frag[t][f]=glCreateShader(GL_FRAGMENT_SHADER);
const char* fshader[]={GLES2_Shader::version, GLES2_Shader::frag_flags[t], GLES2_Shader::fog_flags[f], GLES2_Shader::frag_shader};
glShaderSource(ambient_frag[t][f],4, (const GLchar**)&fshader, 0);
glCompileShader(ambient_frag[t][f]);
glGetShaderiv(ambient_frag[t][f],GL_COMPILE_STATUS, &compiled);
}
for (int l=0;l<=8;l++){
for (int t=0;t<=8;t++){
shader=&shaders[l][t][f];
glAttachShader(shader->ambient_program, ambient_vert[l][f]);
glAttachShader(shader->ambient_program, ambient_frag[t][f]);
glLinkProgram(shader->ambient_program);
glValidateProgram(shader->ambient_program);
glDetachShader(shader->ambient_program, ambient_vert[l][f]);
glDetachShader(shader->ambient_program, ambient_frag[t][f]);
glGetProgramiv(shader->ambient_program,GL_LINK_STATUS, &linked);
shader->vposition=glGetAttribLocation(shader->ambient_program, "aVertexPosition");
shader->vnormal=glGetAttribLocation(shader->ambient_program, "aVertexNormal");
shader->tex_coords=glGetAttribLocation(shader->ambient_program, "aTextureCoord");
shader->tex_coords2=glGetAttribLocation(shader->ambient_program, "aTextureCoord2");
shader->color=glGetAttribLocation(shader->ambient_program, "aVertexColor");
shader->shininess=glGetUniformLocation(shader->ambient_program, "uShine");
shader->model=glGetUniformLocation(shader->ambient_program, "uMMatrix");
shader->view=glGetUniformLocation(shader->ambient_program, "uVMatrix");
shader->proj=glGetUniformLocation(shader->ambient_program, "uPMatrix");
shader->amblight=glGetUniformLocation(shader->ambient_program, "AmbLight");
shader->fogRange=glGetUniformLocation(shader->ambient_program, "fogRange");
shader->fogColor=glGetUniformLocation(shader->ambient_program, "fogColor");
if (l!=0){
shader->lightMat=glGetUniformLocation(shader->ambient_program, "LightMatrix");
shader->lightType=glGetUniformLocation(shader->ambient_program, "LightType");
shader->lightOuterCone=glGetUniformLocation(shader->ambient_program, "LightOuterCone");
shader->lightColor=glGetUniformLocation(shader->ambient_program, "LightColor");
}
if (t!=0){
shader->texflag=glGetUniformLocation(shader->ambient_program, "texFlag");
shader->texmat=glGetUniformLocation(shader->ambient_program, "texMat");
shader->tex_coords_set=glGetUniformLocation(shader->ambient_program, "tex_coord_set");
glUseProgram(shader->ambient_program);
switch(t){
case 8:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler7"), 7);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC7"), 15);
case 7:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler6"), 6);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC6"), 14);
case 6:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler5"), 5);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC5"), 13);
case 5:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler4"), 4);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC4"), 12);
case 4:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler3"), 3);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC3"), 11);
case 3:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler2"), 2);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC2"), 10);
case 2:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler1"), 1);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC1"), 9);
case 1:
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSampler0"), 0);
glUniform1i(glGetUniformLocation(shader->ambient_program, "uSamplerC0"), 8);
}
}
}
}
}
GLuint v,f;
v=glCreateShader(GL_VERTEX_SHADER);
const char* vparticle[]={GLES2_Shader::version, GLES2_Shader::vert_particle};
glShaderSource(v,2, (const GLchar**)&vparticle, 0);
glCompileShader(v);
glGetShaderiv(v,GL_COMPILE_STATUS, &compiled);
f=glCreateShader(GL_FRAGMENT_SHADER);
const char* fparticle[]={GLES2_Shader::version, GLES2_Shader::frag_particle};
glShaderSource(f,2, (const GLchar**)&fparticle, 0);
glCompileShader(f);
glGetShaderiv(f,GL_COMPILE_STATUS, &compiled);
shader_particle.ambient_program=glCreateProgram();
glAttachShader(shader_particle.ambient_program, v);
glAttachShader(shader_particle.ambient_program, f);
glLinkProgram(shader_particle.ambient_program);
glValidateProgram(shader_particle.ambient_program);
glDetachShader(shader_particle.ambient_program, v);
glDetachShader(shader_particle.ambient_program, f);
glGetProgramiv(shader_particle.ambient_program,GL_LINK_STATUS, &linked);
shader_particle.view=glGetUniformLocation(shader_particle.ambient_program, "uVMatrix");
shader_particle.proj=glGetUniformLocation(shader_particle.ambient_program, "uPMatrix");
shader_particle.vposition=glGetAttribLocation(shader_particle.ambient_program, "aVertexPosition");
shader_particle.color=glGetAttribLocation(shader_particle.ambient_program, "aVertexColor");
glUseProgram(shader_particle.ambient_program);
glUniform1i(glGetUniformLocation(shader_particle.ambient_program, "uSampler0"), 0);
shader_particle.texflag=glGetUniformLocation(shader_particle.ambient_program, "texFlag");
v=glCreateShader(GL_VERTEX_SHADER);
const char* vvoxel[]={GLES2_Shader::version, GLES2_Shader::vert_voxel};
glShaderSource(v,2, (const GLchar**)&vvoxel, 0);
glCompileShader(v);
glGetShaderiv(v,GL_COMPILE_STATUS, &compiled);
f=glCreateShader(GL_FRAGMENT_SHADER);
const char* fvoxel[]={GLES2_Shader::version, GLES2_Shader::frag_voxel};
glShaderSource(f,2, (const GLchar**)&fvoxel, 0);
glCompileShader(f);
glGetShaderiv(f,GL_COMPILE_STATUS, &compiled);
shader_voxel.ambient_program=glCreateProgram();
glAttachShader(shader_voxel.ambient_program, v);
glAttachShader(shader_voxel.ambient_program, f);
glLinkProgram(shader_voxel.ambient_program);
glValidateProgram(shader_voxel.ambient_program);
glDetachShader(shader_voxel.ambient_program, v);
glDetachShader(shader_voxel.ambient_program, f);
glGetProgramiv(shader_voxel.ambient_program,GL_LINK_STATUS, &linked);
shader_voxel.model=glGetUniformLocation(shader_voxel.ambient_program, "uMMatrix");
shader_voxel.view=glGetUniformLocation(shader_voxel.ambient_program, "uVMatrix");
shader_voxel.proj=glGetUniformLocation(shader_voxel.ambient_program, "uPMatrix");
shader_voxel.vposition=glGetAttribLocation(shader_voxel.ambient_program, "aVertexPosition");
shader_voxel.vnormal=glGetAttribLocation(shader_voxel.ambient_program, "aVertexNormal");
glUseProgram(shader_voxel.ambient_program);
glUniform1i(glGetUniformLocation(shader_voxel.ambient_program, "uSampler0"), 0);
shader_voxel.texflag=glGetUniformLocation(shader_voxel.ambient_program, "texFlag");
shader_voxel.tex_coords_set=glGetUniformLocation(shader_voxel.ambient_program, "slices");
v=glCreateShader(GL_VERTEX_SHADER);
const char* vstencil[]={GLES2_Shader::version, GLES2_Shader::vert_stencil};
glShaderSource(v,2, (const GLchar**)&vstencil, 0);
glCompileShader(v);
glGetShaderiv(v,GL_COMPILE_STATUS, &compiled);
f=glCreateShader(GL_FRAGMENT_SHADER);
const char* fstencil[]={GLES2_Shader::version, GLES2_Shader::frag_stencil};
glShaderSource(f,2, (const GLchar**)&fstencil, 0);
glCompileShader(f);
glGetShaderiv(f,GL_COMPILE_STATUS, &compiled);
shader_stencil.ambient_program=glCreateProgram();
glAttachShader(shader_stencil.ambient_program, v);
glAttachShader(shader_stencil.ambient_program, f);
glLinkProgram(shader_stencil.ambient_program);
glValidateProgram(shader_stencil.ambient_program);
glDetachShader(shader_stencil.ambient_program, v);
glDetachShader(shader_stencil.ambient_program, f);
glGetProgramiv(shader_stencil.ambient_program,GL_LINK_STATUS, &linked);
shader_stencil.vposition=glGetAttribLocation(shader_stencil.ambient_program, "aVertexPosition");
shader_stencil.color=glGetUniformLocation(shader_stencil.ambient_program, "uColor");
glGenBuffers(1, &stencil_vbo);
glBindBuffer(GL_ARRAY_BUFFER, stencil_vbo);
GLfloat q3[] = {1,1,-1,1,-1,-1,1,-1};
glBufferData(GL_ARRAY_BUFFER,8*sizeof(float),q3,GL_STATIC_DRAW);
glUseProgram(shaders[0][0][0].ambient_program);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClearDepthf(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);