c++ - FreeType OpenGL dynamic Text = abysmal performance -


i'm searching bottlenecks in code , turns out gui 1 of them. well, not gui rather dynamic text drawn there.

initialization

        if (ft_init_freetype(&m_freetype))             throw helpers::exceptionwithmsg("could not init freetype lib");          if (ft_new_face(m_freetype, "res\\fonts\\freesans.ttf", 0, &m_fontface))             throw helpers::exceptionwithmsg("could not open font");          m_shaderid = ... // loads corresponding shader         m_textcolorlocation = glgetuniformlocation(m_shaderid, "color");         m_coordinateslocation = glgetattriblocation(m_shaderid, "coord");          glgenbuffers(1, &m_vbo);          ft_set_pixel_sizes(m_fontface, 0, m_fontsize);         glyph = m_fontface->glyph;          glgentextures(1, &m_texture);          glactivetexture(gl_texture0);         glbindtexture(gl_texture_2d, m_texture);          // require 1 byte alignment when uploading texture data          glpixelstorei(gl_unpack_alignment, 1);          // linear filtering looks best text          gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_linear);         gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_linear);          // clamping edges important 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);          gluseprogram(m_shaderid);             gluniform4f(m_textcolorlocation, m_textcolor.x, m_textcolor.y, m_textcolor.z, m_textcolor.w);         gluseprogram(0); 

what do: initialize freetype, font, initialize shader , uniforms.

then create vbo texturecoordinates, set pixels font, glyph.

now generate texture, activate it, bind it... want set parameters , uniform never changes.

rendering:

    gluseprogram(m_shaderid);      glenable(gl_blend);     glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);      glactivetexture(gl_texture0);     glbindtexture(gl_texture_2d, m_texture);      // linear filtering looks best text      gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_linear);     gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_linear);      // set vbo our vertex data      glenablevertexattribarray(m_coordinateslocation);     glbindbuffer(gl_array_buffer, m_vbo);     glvertexattribpointer(m_coordinateslocation, 4, gl_float, gl_false, 0, 0);      glfloat cursorposx = m_x;     glfloat cursorposy = m_y;     (size_t = 0; < m_text.size(); ++i)     {         // if loading char fails, continue         if (ft_load_char(m_fontface, m_text[i], ft_load_render))             continue;          glteximage2d(gl_texture_2d, 0, gl_alpha, glyph->bitmap.width, glyph->bitmap.rows, 0, gl_alpha, gl_unsigned_byte, glyph->bitmap.buffer);          // calculate vertex , texture coordinates          glfloat x2 = cursorposx + glyph->bitmap_left * m_sx;         glfloat y2 = -cursorposy - glyph->bitmap_top * m_sy;         glfloat w = glyph->bitmap.width * m_sx;         glfloat h = glyph->bitmap.rows * m_sy;          pointstruct box[4] =         {             { x2, -y2, 0, 0 },             { x2 + w, -y2, 1, 0 },             { x2, -y2 - h, 0, 1 },             { x2 + w, -y2 - h, 1, 1 }         };          // draw character on screen         glbufferdata(gl_array_buffer, sizeof box, box, gl_dynamic_draw);         gldrawarrays(gl_triangle_strip, 0, 4);          // advance cursor start of next character          cursorposx += glyph->advance.x / 64 * m_sx;         cursorposy += glyph->advance.y / 64 * m_sy;     }      gldisablevertexattribarray(m_coordinateslocation);     gldeletetextures(1, &m_texture);     gldisable(gl_blend);     gluseprogram(0); 

setting shader , stuff obvious.

for each render call activate texture, bind it, enable vbo store texturecoordinates in. iterate on every character in text load ft_load_char. specify texture glteximage2d, calculate vertex , texture coordinates , draw everything.

that seems highly inefficient, find no way improve performance , yet have readable text.

i wanted set text parameters once in init -> chars boxes.

i wanted set gl_dynamic_draw gl_static_draw... not difference. else can do?

the text render dynamic, changes (or may change) each frame, i'm kind of stuck.

i query performance of stuff query. if not render dynamic text it's low, if render dynamic text gets high... there not else going on in pass, it's drawing gui.

what bothers me

one thing don't understand (may sunny day...)

if not set linear filtering in render-method() strange cube-glyphs, why that? opengl state machine, texture-parameters set 1 bound. if set min , mag filter gl_linear in initialization why isn't enough?

if remove 2 lines in render way better performance query (much lower numbers), doesn't drawn readable.

this absolutely going slow.

for each render call activate texture, bind it, enable vbo store texturecoordinates in. iterate on every character in text load ft_load_char. specify texture glteximage2d, calculate vertex , texture coordinates , draw everything.

the problem, unfortunately, hard. here method use:

  • there 1 texture, gl_red8 format, stores glyphs.

  • whenever new glyph needed, added texture. done calling ft_render_glyph() , copying result texture buffer. if new glyph doesn't fit, whole glyph texture resized , repacked. (i use skyline algorithm packing glyphs since it's simple.)

  • if new glyphs have been added, call gltexsubimage2d(). code should structured called once per frame.

  • to render text, create vbo contains vertex , texture coordinates quads necessary render piece of text. (please understand "quad" means 2 triangles, not gl_quad).

so, when change text want render,

  • you have update vbo, once per frame

  • you might have update texture, once per frame, , happen less glyph texture fills glyphs use.

a way prototype kind of system render all of glyphs in font texture @ first, doesn't work if end using multiple fonts , styles, or if want render chinese, korean, or japanese text.

additional considerations line breaking, glyph substitution, kerning, bidi, general problems international text, how specify styling, et cetera. recommend using harfbuzz in combination freetype. harfbuzz handles difficult glyph substitution , positioning issues. none of strictly necessary if program has english text only.

there libraries of this, have not used them.

an alternative method, if want cut gordian knot, embed web browser chromium (awesomium, webkit, gecko—many choices) in application, , farm out text rendering that.


Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - Bypass Geo Redirect for specific directories -

php - .htaccess mod_rewrite for dynamic url which has domain names -