freetype 2 рдФрд░ opengl рдЯреЗрдХреНрд╕реНрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВ

рдпрд╣ рд╕рдордп рд╣реИ рдХрд┐ рдореБрдЭреЗ freetype2 рдХрд╛ рдкрддрд╛ рдЪрд▓рд╛ред рдЕрдм рдореИрдВ рдЕрдкрдирд╛ рдХреЛрдб рдЬрд░реВрд░рддрдордВрдж рд▓реЛрдЧреЛрдВ рдХреЛ рдЙрдкрд▓рдмреНрдз рдХрд░рд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдХреНрдпреЛрдВрдХрд┐ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╣реИ, рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рд╣рдореЗрд╢рд╛ рд╕рдордп рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдореИрдВ рдлрд╝реНрд░реАрдкрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛрдб рдФрд░ opengl рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛ред рдореИрдВ рдЬрдЯрд┐рд▓ рдХреЛрдб рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддрд╛ред рдореЗрд░реЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИред рдореИрдВрдиреЗ freetype2 рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рдХрдИ рдЯреБрдХрдбрд╝реЗ рджреЗрдЦреЗ, рдФрд░ рд╕рдордЭ рдирд╣реАрдВ рд╕рдХрд╛ рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓реЗрдЦрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдПрдХ рдмрд╣реБрдд рд╣реА рдЬрдЯрд┐рд▓ рдХреЛрдб рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдореЗрд░рд╛ рд╕рд░рд▓ рдХреЛрдб рдкрд╕рдВрдж рдЖрдПрдЧрд╛ред рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдорд▓реНрдЯреА-рд▓рд╛рдЗрди рдЯреЗрдХреНрд╕реНрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХрд▓ рдмрдирд╛рд╡рдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рдореИрдВ рдпрд╣рд╛рдБ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рд╡рд╣ рд╡рд╣ рдЫрд╛рдпрд╛рдХрд╛рд░ рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдХрд┐рддрд╛рдм рд╕реЗ рдмрд╛рд╣рд░ рд▓рд┐рдЦреА рдереАред рдпрд╣ рдХрдИ рддреНрд░рд┐рднреБрдЬреЛрдВ рдкрд░ рдПрдХ рджреЛ рдЖрдпрд╛рдореА рдмрдирд╛рд╡рдЯ рд▓рдЧрд╛рддрд╛ рд╣реИред

рд╢реЗрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рд╣реИред рдореИрдВ рдЙрд╕реЗ рд▓рд┐рдЦрддрд╛ рд╣реВрдВ рдЬрд┐рд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП shader рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╡рд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдореЗрд░реЗ рдкрд╛рд╕ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рд╡рд╣ std :: map container рдХреЗ рдирд╛рдо рд╕реЗ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдо рднреА рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдореБрдЭреЗ рдХреЛрдб рдХреЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрд╕ рд╡рд┐рд╢реЗрд╖ shader рдХрд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдорд┐рд▓ рд╕рдХреЗред

GLuint ShaderManager::createProgram ( const char *param ) { if ( !strncmp ( param, "sprite\0",7 ) ) { const char *vshader = "#version 300 es\n" "layout(location = 0) in vec2 position;\n" "layout(location = 1) in vec2 texCoord;\n" "uniform mat4 transform;\n" "out vec2 v_texCoord;\n" "void main ( )\n" "{\n" " gl_Position = transform * vec4 ( position, 0.0, 1.0 );\n" " v_texCoord = texCoord;\n" "}"; const char *fshader = "#version 300 es\n" "precision mediump float;\n" "in vec2 v_texCoord;\n" "layout(location = 0) out vec4 outColor;\n" "uniform sampler2D s_texture;\n" "void main ( )\n" "{\n" " outColor = texture ( s_texture, v_texCoord );\n" "}"; /*   */ GLuint program = loadProgram ( vshader, fshader ); /*     */ global.programs["sprite"] = program; return program; 

рдЗрд╕рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдПрдХ рдлрд╝реЙрдиреНрдЯ рд╡рд░реНрдЧ рдмрдирд╛рдпрд╛ред рдЗрд╕ рд╡рд░реНрдЧ рдХреА рдПрдХ рд╡рд╕реНрддреБ рдкрд╛рда рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдЧреА, рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрдЧреА рдФрд░ рдПрдХ рдмрдирд╛рд╡рдЯ рдЦреАрдВрдЪреЗрдЧреАред

 #ifndef H_FONT_H #define H_FONT_H #include <stdint.h> #include <ft2build.h> #include <string> #include <vector> #include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengles2.h> #include "gl_mat.hpp" #include "global.hpp" #include <wchar.h> #include FT_FREETYPE_H #include FT_GLYPH_H class Font { public: Font ( ) { } /*   freetype   ttf . */ Font ( const char *ttf_file ); /*     */ void setPos ( int x, int y ); /*    .   *\1     . *\2  . *\3       . *\4       . *\5    . *\6   . *\7   . *\8   . *          */ void init ( wchar_t *text, int fontSize, int align, int valign, int space, uint8_t r, uint8_t g, uint8_t b ); /*    */ void setSize ( int w, int h ); /*   */ void draw ( ); private: FT_Face face = 0; /*    */ float *texture; /*    */ float *vertices; /*    :  */ int width; /*    :  */ int height; /*     */ int sampler; /* id  */ GLuint textureid; /*  x */ int x; /*  y */ int y; /*    glOrtho */ float ortho[4][4]; /*      */ float translate[4][4]; /*    */ float result[4][4]; /*   */ unsigned int program; FT_Library ft_library; FT_Face ttf; }; #endif 

рдЦреИрд░, рдХреНрд▓рд╛рд╕ рддреИрдпрд╛рд░ рд╣реИред рдЕрдм рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ sdl2 рдХреЗ рд╕рд╛рде рдПрдВрдбреНрд░реЙрдЗрдб рдкрд░ рдПрдХ рдЧреЗрдо рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдкреАрд╕реА рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЗрд╕рд▓рд┐рдП, рдореБрдЭреЗ gles2 рдФрд░ opengl рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдХреНрд░реАрди рдкрд░ рдбреЗрдЯрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдПрдХрд▓ рддрд░реАрдХрд╛ рдкрддрд╛ рд╣реИред

рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

 #include "font.hpp" Font::Font ( const char *ttf_file ) { /*        *       android,    cpp  glm. *   ,           *        */ glm::clearMatrix4x4 ( &ortho[0] ); glm::clearMatrix4x4 ( &translate[0] ); glm::clearMatrix4x4 ( &result[0] ); /*       */ program = global.programs["sprite"]; /*       ,     */ int width = global.width; int height = global.height; /*     ,       *  2d  */ glm::ortho ( &ortho[0], 0.0f, width, 0.0f, height, 0.0f, 1.0f ); /*     */ setPos ( 0, 0 ); /*   freetype2. */ FT_Init_FreeType( &ft_library ); /*     */ #ifdef __ANDROID__ FT_NewFace ( ft_library, ttf_file, 0, &face ); #else char *path = (char *) new char[255]; sprintf ( path, "assets/%s", ttf_file ); FT_New_Face ( ft_library, path, 0, &face ); delete[] path; #endif } /*      */ void Font::init ( wchar_t *es, int fontSize, int align, int vert, int space, uint8_t r, uint8_t g, uint8_t b ) { /*      */ FT_Set_Pixel_Sizes ( face, 0, fontSize ); FT_Glyph glyph; int w = 0; unsigned int h = 0; unsigned int maxh = 0; unsigned int toprow = 0; /*        ,     *    i,     . */ int len = wcslen ( es ); /*           ,    *         .     .  *    */ for ( int i = 0; i < len; i++ ) { /*    */ wchar_t charcode = es[i]; /*       bitmap  */ FT_Load_Char ( face, charcode, FT_LOAD_RENDER ); FT_UInt glyph_index = FT_Get_Char_Index ( face, charcode ) FT_Load_Glyph ( face, glyph_index, FT_LOAD_DEFAULT ); FT_Render_Glyph ( face->glyph, FT_RENDER_MODE_NORMAL ); FT_Get_Glyph ( face->glyph, &glyph ); FT_Glyph_To_Bitmap ( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph; FT_Bitmap bitmap = bitmap_glyph->bitmap; /*      */ w += bitmap.width; /*        . */ int resize = bitmap.rows > bitmap_glyph->top ? bitmap.rows - bitmap_glyph->top : bitmap_glyph->top - bitmap.rows; /*         */ if ( h < bitmap.rows + resize ) h = bitmap.rows + resize; /*        */ if ( toprow < bitmap.rows ) toprow = bitmap.rows; if ( maxh < bitmap.rows + bitmap_glyph->top ) maxh = bitmap.rows + bitmap_glyph->top; /*    ,   w   ,    *  */ if ( charcode == ' ' ) w += space; /*    ' ' *           */ if ( charcode == '\n' ) { h += vert + maxh; FT_Done_Glyph ( glyph ); continue; } /*    ,  align   ,     */ w += align; FT_Done_Glyph ( glyph ); } /*      , *        */ if ( h <= 0 ) h = maxh; uint8_t im[h][w]; /*    */ memset ( &im[0][0], 0, w * h * sizeof ( uint8_t ) ); int ih = 0; int iw = 0; int posy = 0; int topy = 0; int maxwidth = 0; for ( int i = 0; i < len; i++ ) { wchar_t charcode = es[i]; FT_Load_Char ( face, charcode, FT_LOAD_RENDER ); FT_UInt glyph_index = FT_Get_Char_Index ( face, charcode ); FT_Load_Glyph ( face, glyph_index, FT_LOAD_DEFAULT ); FT_Render_Glyph ( face->glyph, FT_RENDER_MODE_NORMAL ); FT_Get_Glyph ( face->glyph, &glyph ); FT_Glyph_To_Bitmap ( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph; FT_Bitmap bitmap = bitmap_glyph->bitmap; /*      */ posy = bitmap_glyph->top; /*   ,       */ posy = bitmap.rows - posy; topy = toprow - bitmap.rows; /*   ,  ih -    ,     , *   */ if ( charcode == '\n' ) { ih += maxh; iw = 0; FT_Done_Glyph ( glyph ); continue; } for ( unsigned int y = 0, i = 0; y < bitmap.rows; y++ ) { for ( unsigned int x = 0; x < bitmap.width; x++, i++ ) { if ( ( ih + posy + y + topy ) > h ) { if ( posy < 0 ) posy = abs ( posy ); } /*         *      gray,       */ im [ ih + posy + y + topy ] [ iw + x ] = bitmap.buffer[i]; } } /*   */ iw += bitmap.width; /*     */ iw += align; if ( maxwidth < iw ) maxwidth = iw; if ( charcode == ' ' ) { iw += space; } FT_Done_Glyph ( glyph ); } iw = maxwidth; width = iw; height = h; unsigned int size = width * height; /*       */ uint8_t *image_data = new uint8_t [ size * 4 ]; /*      */ memset ( image_data, 255, size * 4 * sizeof ( uint8_t ) ); for ( unsigned int i = 0, y = 0; i < size; y++ ) { for ( int x = 0; x < width; x++, i++ ) { /*          */ image_data[ 4 * i + 3] = im [ y ][ x ]; /*    */ image_data[ 4 * i + 0] = r; image_data[ 4 * i + 1] = g; image_data[ 4 * i + 2] = b; } } /*      */ glGenTextures ( 1, &textureid ); glBindTexture ( GL_TEXTURE_2D, textureid ); glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data ); 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); /*      */ setSize ( width, height ); /*   ,       image_data   . */ delete[] image_data; } void Font::setSize ( int w, int h ) { /*   ,       ,     */ if ( vertices ) delete[] vertices; if ( texture ) delete[] texture; vertices = new float [ 12 ]; vertices[0] = 0; vertices[1] = 0; vertices[2] = 0; vertices[3] = h; vertices[4] = w; vertices[5] = 0; vertices[6] = w; vertices[7] = 0; vertices[8] = w; vertices[9] = h; vertices[10] = 0; vertices[11] = h; /*        ,       *  */ texture = new float [ 12 ]; texture[0] = 0; texture[1] = 1; texture[2] = 0; texture[3] = 0; texture[4] = 1; texture[5] = 1; texture[6] = 1; texture[7] = 1; texture[8] = 1; texture[9] = 0; texture[10] = 0; texture[11] = 0; } void Font::setPos ( int x, int y ) { /*    ,    */ this->x = x; this->y = y; glm::translate ( &translate[0], x, y, 0 ); glm::sumMatrix ( &result[0], &translate[0], &ortho[0] ); } void Font::draw ( ) { /*      */ glUseProgram ( program ); sampler = glGetUniformLocation ( program, "s_texture" ); glActiveTexture ( GL_TEXTURE0 ); glBindTexture ( GL_TEXTURE_2D, textureid ); glUniform1i ( sampler, 0 ); GLint projection_location = glGetUniformLocation ( program, "transform" ); glUniformMatrix4fv ( projection_location, 1, GL_FALSE, &result[0][0] ); glEnableVertexAttribArray ( 0 ); glEnableVertexAttribArray ( 1 ); /*     */ glVertexAttribPointer ( 0, 2, GL_FLOAT, GL_FALSE, 0, vertices ); /*     */ glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, 0, texture ); /*    */ glDrawArrays ( GL_TRIANGLES, 0, 12 ); glDisableVertexAttribArray ( 0 ); glDisableVertexAttribArray ( 1 ); } 

рдХреЛрдб рд╕реЗ, рдЖрдк рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

  Font *font = new Font ("anonymous.ttf"); wchar_t * text = L" habr.    .   freetype  opengl.\n" "  freetype   .\n" "    ,       "; font->init ( text, 21, 1, 4, 4, 0, 0, 0 ); font->setPos ( 100, 100 ); 

рдЫрд╡рд┐

Source: https://habr.com/ru/post/hi441986/


All Articles