Freetype、OpenGL 中的字符奇怪地居中

问题描述 投票:0回答:1

我正在尝试在按钮内渲染一些文本(这只是按钮大小的 vec2 和按钮位置的 vec2),并且我正在尝试将按钮内的文本居中。它适用于具有相同高度的字符,例如“a”、“c”、“x”、“z”以及所有大写字母。但是一旦我添加了不同高度的字母,文本居中就会变得混乱。

Image to show that the text rendering gets messed up Image to show that the text rendering gets messed up

这是我用来渲染文本的代码:

for (auto& item : buttons)
{
    buttonShader->use();
    buttonShader->setTexture2D("texture1", defaultTexture, 0);

    // Calculate the transform matrix for the button (NOT the text), i think it's relevant
    glm::mat4 transform = glm::mat4(1.0f);
    transform = glm::translate(transform, glm::vec3(item.position.x, item.position.y, 0.0f));
    transform = glm::scale(transform, glm::vec3(item.buttonSize.x, item.buttonSize.y, 1.0f));

    // This is where I set the uniforms inside the shader, irrelevant code

    // This is where I render the button with glDrawElements, irrelevant

    shader->use();
    glBindVertexArray(VAO);

    const std::string& text = item.text;
    const std::string& fontPath = item.font;

    float buttonWidth = item.buttonSize.x;
    float buttonHeight = item.buttonSize.y;
    float x = item.position.x - buttonWidth / 2.0f;
    float y = item.position.y - buttonHeight / 2.0f;

    glm::vec2 scale = item.textSize; 
    glm::vec3 color = glm::vec3(item.textColor.x, item.textColor.y, item.textColor.z);

    shader->setVec3("textColor", color);

    // Calculate the total width and height of the text
    float totalWidth = 0.0f;
    float maxHeight = 0.0f;
    for (auto c = text.begin(); c != text.end(); ++c) {
        Character ch = Fonts[fontPath][*c];
        totalWidth += (ch.Advance >> 6) * scale.x; // Advance is in 1/64 pixels
        maxHeight = std::max(maxHeight, static_cast<float>(ch.Size.y));
    }

    float startX = x + (buttonWidth - totalWidth) / 2.0f;
    float startY = y + (buttonHeight - maxHeight * scale.y) / 2.0f;

    for (auto c = text.begin(); c != text.end(); ++c) {
        Character ch = Fonts[fontPath][*c];

        float xpos = startX + ch.Bearing.x * scale.x; // Apply x scaling
        float ypos = startY + (ch.Size.y - ch.Bearing.y) * scale.y; 

        float w = ch.Size.x * scale.x; 
        float h = ch.Size.y * scale.y; 
        float vertices[6][4] = {
            { xpos,     ypos + h,   0.0f, 0.0f },
            { xpos,     ypos,       0.0f, 1.0f },
            { xpos + w, ypos,       1.0f, 1.0f },

            { xpos,     ypos + h,   0.0f, 0.0f },
            { xpos + w, ypos,       1.0f, 1.0f },
            { xpos + w, ypos + h,   1.0f, 0.0f }
        };
        glBindTexture(GL_TEXTURE_2D, ch.TextureID);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glDrawArrays(GL_TRIANGLES, 0, 6);

        startX += (ch.Advance >> 6) * scale.x;
    }
}
c++ opengl glm-math freetype
1个回答
0
投票

我看到两个问题:

  1. 您应该从基线分别计算单独的 maxHeight 和 minHeight (或使用已提供的行间距/字体度量高度)。
    p
    d
    将具有相似的“大小”值,但在基线上的位置不同,因此您在计算时会低估按钮所需的大小。
  2. (造成你错误定位的主要原因):你在计算位置时颠倒了符号。如果 +Y 向上,则需要从底部 BASELINE -(SizeY - BearingY)开始,向上到达 BASELINE + BearingY。或者+Y的另一种方式是向下的。请参阅 freetype 文档中的图表:freetype glyph bearing documentation
© www.soinside.com 2019 - 2024. All rights reserved.