Talk:OpenGL Programming/Modern OpenGL Tutorial Text Rendering 02

Hello. I have a problem with text rendering in this tutorial. First tutorial worked fine for me but this one it shows me just squares, other times shows nothing or shows transparent squares. I googled but found nothing. I learn OpenGL from internet tutorials so I am not so good with OpenGL. I am using Ubuntu 12.04, opengl 3.3 compatibility profile. I read the comment from the first tutorial and tried that method but it doesn't help. Please help to solve this problem, thanks.

Update: I see now the line that resolves the problem that i had : /* you might as well save this value as it is needed later on */ int atlas_width = w; It wasn't there before.

By the way great tutorial, i searched a long time such a tutorial to teach how to draw fonts in openGL, and this is even greater because you can make use of any .tff fonts available on internet. Great work.

Bytheway shouldn't be i instead of *p in:

c[*p].ax = g->advance.x >> 6; c[*p].ay = g->advance.y >> 6; c[*p].bw = g->bitmap.width; c[*p].bh = g->bitmap.rows; c[*p].bl = g->bitmap_left; c[*p].bt = g->bitmap_top; c[*p].tx = (float)x / w;

to make it work correctly?

I had to swap the second and third points when generating the triangle coordinates for rendering, otherwise I only got half of each character.

217.46.216.121 (discuss) 17:38, 6 March 2014 (UTC)

On Ubuntu (14.04) I had a problem with "noise" in my font atlas texture - the parts not filled in by the characters were filled with garbage. This manifested itself by thin borders around the letters when I rendered. The problem was caused by initialising the texture with a null pointer, thus: If I instead initialised with an array of unisgned chars all set to 0 the noise went away. On windows this never seemed to be a problem.

--

for OpenGL 3.3 core profile vao must be bind I too had problem with noise in texture on linux if you see only half of each character: glDisable(GL_CULL_FACE);

fuzzy text
instead of

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

use:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

it give better result (ie prevent blurring of text) for me.

another less better trick (if do not want to use above): [just for reference]

the coordinate of the text that will be draw need to be multiple of `2.0 / surface_width` (for x)  and `2.0 / surface_height` (for y).

x += fmodf(fabs(x), 2.0 / surface_width); y += fmodf(fabs(y), 2.0 / surface_height);

but this has side effect of changing coordinate and in some special case (surface width or height), still show blurry text.

Fixing problem with GL_LINEAR and artifacts
If you want to use GL_LINEAR to get the appearance of anti-aliasing, but are getting line artifacts at the edges of your glyphs, the real solution is to add padding to each glyph in the atlas. The reason there are artifacts is that GL_LINEAR averages the nearest 4 texels and since the glyphs are densely packed, the averaging is picking up a portion of the next glyph.

And, if you also pad vertically, you'll clean up the hard edge at the top of the glyph, so all edges will appear anti-aliased.

Note: m_fontPadding = 1

Here's how you make the changes:

// When measuring the glyphs for(int i = 32; i < 128; ++i) {       if(FT_Load_Char(face, i, FT_LOAD_RENDER)) {           fprintf(stderr, "Loading character %c failed!\n", i); continue; }       w += g->bitmap.width + m_fontPadding; // add padding to allow GL_LINEAR interpolation to work h = std::max(h, g->bitmap.rows); }   h += m_fontPadding;

And, in the glTexSubImage code:

for(int i = 32; i < 128; ++i) {       if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue; glTexSubImage2D(GL_TEXTURE_2D, 0, x, m_fontPadding, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer); // Save the glyph locations c[i].ax = g->advance.x >> 6; c[i].ay = g->advance.y >> 6; c[i].bw = g->bitmap.width; c[i].bh = g->bitmap.rows + m_fontPadding; c[i].bl = g->bitmap_left; c[i].bt = g->bitmap_top; c[i].tx = (float)x / w;       x += g->bitmap.width + m_fontPadding; }

Improving glyph/texture clarity using gamma correction
If you've implemented nearly all of the aforementioned improvements to FreeType rendering (pixel alignment, padding, nearest sampling), but have not been satisfied with the fuzziness of the finished text on screen - try this simple step. For single-sampled textures, apparent texture sharpness can be enhanced in the fragment shader using a power function:

float gamma = 2.2;//seems to work well (traditional CRT correction factor!?)

vec4 outColor = texture(tex, frag.tcoord.xy);//r-channel contains glyph data

outColor = textColor * pow(outColor.r, 1.f/gamma);//NEW CORRECTION FACTOR

The results really help with thin/small fonts!

GL_ALPHA deprecation > GL 3.0
glTexture and glSubTexture no longer support writing to just GL_ALPHA. Instead, use and write to GL_RED and update your frag shader accordingly.