【问题标题】:Speed up text rendering performance openGL加快文本渲染性能 openGL
【发布时间】:2015-10-27 08:16:30
【问题描述】:

我使用 FreeType 库来提取每个字形信息,例如宽度、高度和位图。这是在 init 函数中完成的,我并不真正关心它所花费的时间。我将每个字符信息存储在地图容器中,以便以后可以轻松访问每个字符。

在渲染时,我读取字符串并使用字符串迭代器循环遍历每个字符并使用字形参数创建要在其上绘制位图的多边形。

使用 VAO 和 VBO 绘制多边形

为了让它透明,我使用混合,着色器用于着色。

这是我的渲染函数的样子:

void CFreeType::RenderText(std::string text, int posX, int posY, Vector3d color)
{
    ViewOrtho(RESx, RESy);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_DEPTH_TEST);
    textShader->Use();
    glUniform3dv(textColor_uniform_location, 1, color.v);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    this->x = posX;
    this->y = posY + FontHeight;

    std::string::const_iterator c;
    for(c = text.begin(); c != text.end(); c++)
    {
        //Load character from map
        Character ch = Characters[*c];

        //If we hit the '^' character, we probably want to change the text color
        if(*c == '^')
        {
            //Check if the next character is a number, if so, change the text color and skip this character.
            c++;
            ch = Characters[*c];
            if(isdigit(*c))
            {
                glUniform3dv(glGetUniformLocation(textShader->GetProgram(), "textColor"), 1, Color[*c-48].v); // *c-48 for conversion from ASCII to in int - '0' == 48
                continue;
            }
            //In the other case go back to previous character ('^').
            else
            {
                c--;
                ch = Characters[*c];
            }
        }

        //If we hit a new line character, move the new line below the previous and skip this character.
        else if(*c == '\n')
        {
            x = posX;
            y += FontHeight;
            continue;
        }

        //If we hit tab character, insert 4 spaces
        else if(*c == '\t')
        {
            x += (Characters[' '].AdvanceX >> 6) << 2; //Bit shifting is hopefuly a bit faster than multiplying/dividing.
            continue;
        }

        xpos = x + ch.Bearing.x;
        ypos = y - ch.Bearing.y;
        font_width = ch.Size.x;
        font_height = ch.Size.y;

        float vertices[6][4] = {
            {xpos, ypos, 0.0, 0.0},
            {xpos, ypos + this->font_height, 0.0, 1.0},
            {xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},

            {xpos, ypos, 0.0, 0.0},
            {xpos + this->font_width, ypos + this->font_height, 1.0, 1.0},
            {xpos + this->font_width, ypos, 1.0, 0.0}
        };

        //Render character
        glBindTexture(GL_TEXTURE_2D, ch.TextureID);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        x += (ch.AdvanceX >> 6);
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    ViewPerspective();

    textShader->StopShader();
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
}

我曾考虑使用显示列表代替 VBO,但我认为不会有任何改进。

绘制大约 400 个字符时,我只能获得大约 165 FPS,而没有渲染任何字符时,我几乎可以达到 390 FPS。

如果能提供任何有助于提高文本呈现性能的帮助,我将不胜感激。

【问题讨论】:

  • 您可能会在Code Review 上得到更好的回复。
  • 我现在不想在两个网站上创建重复的内容,也许我以后会尝试一下,无论如何感谢您的建议:)

标签: c++ performance opengl freetype text-rendering


【解决方案1】:

纹理绑定和glDrawArrays() 每个字符?不是最好的方法。

最小化纹理绑定和绘制调用的数量:

  1. Glom all your glyphs into (ideally) a single texture atlas
  2. 将一帧文本的所有顶点信息放入单个 VBO
  3. 使用单个 glDrawArrays() 调用为框架绘制所有字符串

【讨论】:

  • 但我仍然需要将纹理图集绑定到多个多边形,对吧?
  • @ProXicT:不,如果你所有的字形都在一个纹理中并且你的 VBO 设置了适当的纹理坐标,你只需要一个纹理绑定。
  • 哦,太尴尬了。我现在明白了。谢谢!
  • 您想要制作纹理的是一种称为“装箱算法”的东西。这里有一些想法:stackoverflow.com/questions/21078959/…
  • 我有一个想法,即在初始化时间内在屏幕上绘制所有字符并“捕获”屏幕并保存纹理,就像我使用 FBO 所做的那样。文本坐标可以简单地从纹理中的字符位置计算出来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 2010-09-17
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多