Hello,
I am a beginner to OpenGL, and I am currently trying to add Font rendering support to my app. I have reduced my program to the bare minimum to demonstrate the issues I am having.
I can successfully load a font, and print it to the screen using the command prompt, so I know the FreeType code is ok.
I can also draw a quad onto the screen, and the colour appears to change depending on which letter I try to draw, so it seems that something is happening in the rendering code, but I can’t seem to figure out what.
Can anyone shed any light on this?
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW. Always include it before gl.h and glfw.h, since it's a bit magic.
#include <PhoenixEngineDependencies/glew/glew.h>
// Include GLFW
#include <PhoenixEngineDependencies/glfw/glfw3.h>
// Include GLM
#include <PhoenixEngineDependencies/glm/glm.hpp>
#include <PhoenixEngineDependencies/glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <iostream>
#include <fstream>
using namespace std;
#include "model_obj.h"
#include <PhoenixEngineDependencies/ttmath/ttmath.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_TRIGONOMETRY_H
int windowWidth = 800;
int windowHeight = 800;
void controls(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(action == GLFW_PRESS)
if(key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GL_TRUE);
}
GLFWwindow* initWindow(const int resX, const int resY)
{
if(!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW
");
return NULL;
}
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
// Open a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow(resX, resY, "TEST", NULL, NULL);
if(window == NULL)
{
fprintf(stderr, "Failed to open GLFW window.
");
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, controls);
// Get info of GPU and supported OpenGL version
printf("Renderer: %s
", glGetString(GL_RENDERER));
printf("OpenGL version supported %s
", glGetString(GL_VERSION));
glEnable(GL_DEPTH_TEST); // Depth Testing
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
return window;
}
const char* textvertexSource =
"version 150
"
"in vec4 coord;"
"out vec2 texcoord;"
"void main {"
" gl_Position = vec4(coord.xy, 0, 1);"
" texcoord = coord.zw;"
"}";
const char* textfragmentSource =
"version 150
"
"in vec2 texcoord;"
"uniform sampler2D tex;"
"uniform vec4 color;"
"void main() {"
" gl_FragColor = vec4(1, 1, 1, texture2D(tex, texcoord).a * color;"
"}";
FT_Library ft;
FT_Face face;
char* fontName = "tr.ttf";
unsigned char Image[800][800];
bool run = false;
void my_draw_bitmap( FT_Bitmap* bitmap, FT_Int x, FT_Int y)
{
if(run == true)
return;
run = true;
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width;
FT_Int y_max = y + bitmap->rows;
for ( j = y, q = 0; j < y_max; j++, q++ )
{
for ( i = x, p = 0; i < x_max; i++, p++ )
{
if ( i<0 || j<0 || i>=800 || j>=800 ) continue;
Image[j][i] |= bitmap->buffer[q * bitmap->width + p];
if(Image[j][i]==0) {
printf("-");
}
else{
printf("0");
}
}
printf("
");
}
}
GLuint textureID;
int main(int argc, char** argv)
{
GLFWwindow* window = initWindow(windowWidth, windowHeight);
GLenum err = glewInit();
if(FT_Init_FreeType(&ft))
printf("Could not initiate freetype library.");
if(FT_New_Face(ft, fontName, 0, &face))
{
printf("Could not load font: ");
printf(fontName);
}
if( NULL != window )
{
glViewport(0, 0, windowWidth, windowHeight);
glClearColor(0.5, 0.8, 0.3, 1.0);
float points[] = {
-0.5f, -0.5f, 0,
-0.5f, 0.5f, 0,
0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
-0.5f, 0.5f, 0,
0.5f, 0.5f, 0
};
GLuint vbo = 0;
glGenBuffers (1, &vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, 18 * sizeof (float), points, GL_STATIC_DRAW);
GLuint vao = 0;
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
glEnableVertexAttribArray (0);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
const char* vertex_shader =
"#version 330 core"
"layout(location=0) in vec4 vVertex; //object space vertex"
"out vec2 vUV; // texture coordinates for texture lookup in the fragment shader"
"void main()"
"{"
" gl_Position = vec4(vVertex.xy,0,1);"
" vUV = vVertex.zw; // texture coordinate"
"}"
;
const char* fragment_shader =
"#version 330 core"
"layout (location=0) out vec4 vFragColor;"
"smooth in vec2 vUV;"
"uniform sampler2D textureMap;"
"void main()"
"{"
" vFragColor = texture(textureMap, vUV);"
"}"
;
GLuint vs = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vs, 1, &vertex_shader, NULL);
glCompileShader (vs);
GLuint fs = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fs, 1, &fragment_shader, NULL);
glCompileShader (fs);
GLuint shader_programme = glCreateProgram ();
glAttachShader (shader_programme, fs);
glAttachShader (shader_programme, vs);
glLinkProgram (shader_programme);
err = FT_Set_Char_Size(
face, /* handle to face object */
0, /* char_width in 1/64th of points */
16*64, /* char_height in 1/64th of points */
300, /* horizontal device resolution */
300 ); /* vertical device resolution */
if(err){printf("FAIL1");}
err = FT_Set_Pixel_Sizes(
face, /* handle to face object */
0, /* pixel_width */
16 ); /* pixel_height */
if(err){printf("FAIL2");}
FT_GlyphSlot slot;
while(!glfwWindowShouldClose(window))
{
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
slot = face->glyph;
FT_Load_Char(face, 'A', FT_LOAD_RENDER);
my_draw_bitmap( &slot->bitmap,
300 + slot->bitmap_left,
200 - slot->bitmap_top );
glGenTextures( 1, &textureID );
glActiveTexture( GL_TEXTURE0 );
glBindTexture(GL_TEXTURE_2D, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable (GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram (shader_programme);
glBindVertexArray (vao);
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGB,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
glDrawArrays (GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}