afq | Дата: Среда, 27 Февраля 2019, 07:49 | Сообщение # 1 |
Разработчик
Сейчас нет на сайте
| Всем привет. Я достиг успеха в работе с freetype2. Пусть может быть эта тема будет кому нибудь полезна. Может кто в интернете незнает как работать с freetype, зайдет в эту тему и скачает текст класса. Итак, вот чего я достиг. С помощью моего кода текст можно выводить в несколько строк. Эти строки будут включены в одну текстуру. Класс ведь правда? Одной текстурой рисовать несколько строк. А то я видел какие то примеры, вообще не понятные. Там как то странно нужно рисовать строки. В общем, вот что получается.
Вот как вызвать функцию.
Код wchar_t * text = L"привет gcup, я пишу в линуксе с sdl2 и opengl.\n" "Мне нравиться когда у меня начинает что-то получаться.\n" "А также я считаю что эта тема может пригодиться многим, кто хочет работать с freetype2.\n" "И так, код будет снизу!"; font->init ( text, 21, 1, 4, 4, 0, 0, 0 );
Функция init принимает параметры. \1 текст \2 размер шрифта \3 расстояние между шрифтами по горизонтали в пикселях \3 расстояние между шрифтами по вертикали в пикселях \3 размер пробела в пикселях \4 красный цвет \5 зеленый цвет \6 синий цвет
Вот код font.hpp
Код #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 ( ) { } Font ( const char *ttf_file ); void setPos ( int x, int y ); 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; GLuint textureid; int x; int y; int max_draw; float ortho[4][4]; float translate[4][4]; float result[4][4]; unsigned int program; FT_Library ft_library; FT_Face ttf;
}; #endif
Вот код font.cpp
Код #include "font.hpp"
Font::Font ( const char *ttf_file ) { glm::clearMatrix4x4 ( &ortho[0] ); glm::clearMatrix4x4 ( &translate[0] ); glm::clearMatrix4x4 ( &result[0] );
program = global.programs["sprite"]; int width = global.width; int height = global.height; glm::ortho ( &ortho[0], 0.0f, width, 0.0f, height, 0.0f, 1.0f ); setPos ( 0, 0 );
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 ); free ( 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; int len = wcslen ( es ); 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; w += bitmap.width;
int resize = bitmap.rows - bitmap_glyph->top; h = bitmap.rows + resize; if ( toprow < bitmap.rows ) toprow = bitmap.rows; if ( maxh < bitmap.rows + bitmap_glyph->top ) maxh = bitmap.rows + bitmap_glyph->top;
if ( charcode == ' ' ) w += space; if ( charcode == '\n' ) { h += vert + maxh; FT_Done_Glyph ( glyph ); continue; } w += align;
FT_Done_Glyph ( glyph ); }
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;
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++ ) { 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 ); delete[] image_data;
} void Font::setSize ( int w, int h ) { 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 ); }
Вот код шейдера
Код 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" "}";
В пространстве glm содержаться функции по перемещению текста. Если надо, могу выложить.
Добавлено (27 Февраля 2019, 07:54) --------------------------------------------- Как блин сделать чтобы из поисковиков на эту тему тоже была ссылка?
Сообщение отредактировал afq - Суббота, 02 Марта 2019, 13:48 |
|
| |