I'm trying to implement font rendering and have got into some trouble with glyph metrics. Here's the code where I get the metrics:
Glyph gl;
gl.width = face->glyph->metrics.width / 64;
gl.height = face->glyph->metrics.height / 64;
gl.character = i;
gl.advance = face->glyph->metrics.horiAdvance / 64;
gl.bearingX = face->glyph->metrics.horiBearingX / 64;
gl.bearingY = face->glyph->metrics.horiBearingY / 64;
gl.textureX = this->_textureWidth;
The value of gl.advance
is way too small. Here is a picture of it:
If I'm dividing face->glyph->metrics.horiAdvance
by 40, it looks like this:
The text is now readable, but the advance and X-, Y-bearing still don't look correct. This is what it should look like:
Here is my code where I draw the glyphs:
float aspect = this->_graphics->getMetrics().x / this->_graphics->getMetrics().y;
float offset = 0;
for(unsigned char c : str){
Glyph g = this->_fonts[fontID]->getGlyph(c);
vec2 pos = (position.getRelative() + vec2(offset, 0) + (vec2(g.bearingX, -g.bearingY) / SCALING) * scale - vec2(1, 1))
* vec2(1, -1);
glyphShader->setUniform("position", pos);
glyphShader->setUniform("scale", (vec2(g.width, g.height * aspect) / SCALING) * scale);
glyphShader->setUniform("glyphSize", vec2(g.width, g.height));
glyphShader->setUniform("textureMetrics", this->_fonts[fontID]->getTextureMetrics());
glyphShader->setUniform("textureOffset", vec2(g.textureX, 0));
glyphShader->setUniform("image", 0);
glyphShader->setUniform("color", color);
this->_graphics->getMeshByID(guiInstance->_quadID)->drawMesh();
offset += (g.advance / SCALING) * scale;
}
I'm doing some transformations on position
to move the origin to the top-left corner and flipping the coordinate system on the X-Axis. Then I divide every pixel value by a constant factor, to have the font having the same size on every resolution. The ratio of the glyphs is correct, but not the alignment. And here is my vertex shader:
#version 400
layout(location=0) in vec4 vertPosition;
layout(location=1) in vec2 vertUV;
uniform vec2 position;
uniform vec2 scale;
uniform vec2 glyphSize;
uniform vec2 textureMetrics;
uniform vec2 textureOffset;
out vec2 fragUV;
void main(void){
gl_Position = vertPosition *
vec4(scale, 1, 1) +
vec4(position, 0, 0);
fragUV = vec2(vertUV.x * (glyphSize.x / textureMetrics.x) + (textureOffset.x / textureMetrics.x),
-vertUV.y * (glyphSize.y / textureMetrics.y));
}
Why are the characters misaligned?
You divide by 64.
Since you are using OpenGL to render your text, you need to consider 2 things.
Some of the FreeType fields are representing the size of the font, while others are representing the position. In some cases, you will do arithmetic that combines both position and the size of the font.
The golden rule to remember is when combining size and position, multiply the size by 2.
Glyph gl;
gl.width = face->glyph->metrics.width / 64; //size
gl.height = face->glyph->metrics.height / 64; //size
gl.character = i;
gl.advance = face->glyph->metrics.horiAdvance / 64; //size
gl.bearingX = face->glyph->metrics.horiBearingX / 64; //position
gl.bearingY = face->glyph->metrics.horiBearingY / 64; //position
gl.textureX = this->_textureWidth;
//whenever combining size and position, multiply the size by 2
gl_Position = vertPosition *
vec4(scale, 1, 1) * 2 /*multiply*/ +
vec4(position, 0, 0);
PS: You shouldn't use aspect ratio with the font dimensions. It defeats the purpose of the font designers. The metrics provided by the font designers will give the optimal look for the fonts.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.