【问题标题】:Text alignment in OpenGL with FreeType2OpenGL中的文本对齐与FreeType2
【发布时间】:2014-06-19 08:05:50
【问题描述】:

我正在尝试实现字体渲染,但在字形指标方面遇到了一些问题。 这是我获取指标的代码:

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;

gl.advance 的值太小了。这是它的图片:

如果我将face->glyph->metrics.horiAdvance 除以 40,它看起来像这样:

文本现在可读,但前进和 X、Y 轴承仍然不正确。它应该是这样的:

这是我绘制字形的代码:

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;
}

我正在对position 进行一些转换,以将原点移动到左上角并翻转 X 轴上的坐标系。然后我将每个像素值除以一个常数因子,以使字体在每个分辨率上都具有相同的大小。字形的比例是正确的,但不是对齐。 这是我的顶点着色器:

#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));
}

为什么字符错位?

【问题讨论】:

  • 您绝对不想除以 40,这甚至不是 2 的幂。 FreeType 中的坐标是定点的; 26.6 在这种情况下。整数除以 64 与向右移动 6 几乎相同 - 你会丢失任何坐标的小数部分。我不确定在这个例子中是否会有任何小数坐标,但是如果它们存在,除以 64.0f 而不是 64 应该保留它们。
  • 谢谢,但这并不能解决问题。
  • 另外,由于您没有在视口的所有坐标范围为 [-1,1] 的坐标范围内转换这些顶点,您是否正在补偿这一事实?如果您计算的偏移量应该是像素坐标(窗口空间),那么事情会变得很奇怪。我想这就是 SCALINGscale 的用途,但您还没有展示它们是如何计算的。

标签: c++ opengl text fonts freetype


【解决方案1】:

你除以 64。

由于您使用 OpenGL 来渲染文本,您需要考虑两件事。

  • OpenGL 位置范围从 -1.0f 到 +1.0f。这是 2.0f 的震级。
  • OpenGL 大小范围从 0.0f 到 1.0f。这是 1.0f 的量级。

一些 FreeType 字段代表字体的大小,而另一些则代表位置。在某些情况下,您会进行结合位置和字体大小的算术运算。

要记住的黄金法则是在组合大小和位置时,将大小乘以 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: 您不应该将纵横比与字体尺寸一起使用。它违背了字体设计者的目的。字体设计师提供的指标将为字体提供最佳外观。

【讨论】:

    猜你喜欢
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2021-10-23
    • 2012-08-05
    相关资源
    最近更新 更多