# include "text.hpp"
# include <glm/glm.hpp>
# include <glm/gtc/matrix_transform.hpp>
# include <glm/gtc/type_ptr.hpp>
# include <glad/glad.h>
# include <GLFW/glfw3.h>
# include <ft2build.h>
# include "config.hpp"
# include FT_FREETYPE_H
void Text : : render ( const std : : string & text , float x , float y , float scale , glm : : vec3 color ) {
text_shader . use ( ) ;
glm : : mat4 projection = glm : : ortho ( 0.0f , static_cast < float > ( WINDOW_WIDTH ) , 0.0f , static_cast < float > ( WINDOW_HEIGHT ) ) ;
text_shader . setMat4 ( " projection " , projection ) ;
glUniform3f ( glGetUniformLocation ( text_shader . ID , " textColor " ) , color . x , color . y , color . z ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindVertexArray ( text_vao ) ;
for ( auto c : text ) {
auto & ch = characters . at ( c ) ;
float xpos = x + ch . bearing . x * scale ;
float ypos = y - ( ch . size . y - ch . bearing . y ) * scale ;
float w = ch . size . x * scale ;
float h = ch . size . y * scale ;
float 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 }
} ;
// rander glyph texture over quad
glBindTexture ( GL_TEXTURE_2D , ch . texture_id ) ;
// update content of VBO memory
glBindBuffer ( GL_ARRAY_BUFFER , text_vbo ) ;
glBufferSubData ( GL_ARRAY_BUFFER , 0 , sizeof ( vertices ) , vertices ) ;
glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
// render quad
glDrawArrays ( GL_TRIANGLES , 0 , 6 ) ;
x + = ( ch . advance > > 6 ) * scale ;
}
glBindVertexArray ( 0 ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
}
void Text : : load_font ( ) {
FT_Library ft ;
int fail = FT_Init_FreeType ( & ft ) ;
dbc : : check ( fail = = 0 , " FreeType failed. " ) ;
FT_Face face ;
fail = FT_New_Face ( ft , font . c_str ( ) , 0 , & face ) ;
dbc : : check ( fail = = 0 , " Failed to load font. " ) ;
// load the font bitmaps
FT_Set_Pixel_Sizes ( face , 0 , font_size ) ;
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
for ( unsigned char c = 0 ; c < 255 ; c + + ) {
fail = FT_Load_Char ( face , c , FT_LOAD_RENDER ) ;
dbc : : check ( fail = = 0 , $ F ( " Failed to load char {} " , int ( c ) ) ) ;
unsigned int texture = UINT_MAX ;
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 ) ;
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 ) ;
characters . try_emplace ( c ,
texture ,
glm : : ivec2 ( face - > glyph - > bitmap . width , face - > glyph - > bitmap . rows ) ,
glm : : ivec2 ( face - > glyph - > bitmap_left , face - > glyph - > bitmap_top ) ,
static_cast < unsigned int > ( face - > glyph - > advance . x ) ) ;
}
// unbind
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
// cleanup
FT_Done_Face ( face ) ;
FT_Done_FreeType ( ft ) ;
// create teh vao/vbo
glGenVertexArrays ( 1 , & text_vao ) ;
glGenBuffers ( 1 , & text_vbo ) ;
glBindVertexArray ( text_vao ) ;
glBindBuffer ( GL_ARRAY_BUFFER , text_vbo ) ;
glBufferData ( GL_ARRAY_BUFFER , sizeof ( float ) * 6 * 4 , NULL , GL_DYNAMIC_DRAW ) ;
glEnableVertexAttribArray ( 0 ) ;
glVertexAttribPointer ( 0 , 4 , GL_FLOAT , GL_FALSE , 4 * sizeof ( float ) , 0 ) ;
glBindVertexArray ( 0 ) ;
}