Speed up text rendering performance openGL

守給你的承諾、 提交于 2020-01-16 01:10:12

问题


I use the FreeType library to pull out each glyph info such as width, height and bitmap. This is done in init function, where I don't really care about the time it takes. I store each character info in map container, so I can later access each character easily.

On render time I read the string and using string iterator I loop through each character and use the glyph parameters to create polygons on which I want to draw the bitmap.

The polygons are drawn using VAO together with VBO

To make it transparent, I use blending, and a shader is used for coloring.

This is what my rendering function looks like:

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

I was thinking of using a display list instead of VBO, but I don't think it would make any improvement.

With approximately 400 characters drawn, I get only around 165FPS and without any character rendered I get almost 390FPS.

I would appreciate any help leading to an enhancement of the text rendering performance.


回答1:


A texture bind and glDrawArrays() per character? Not the best way to do it.

Minimize the number of texture binds & draw calls:

  1. Glom all your glyphs into (ideally) a single texture atlas
  2. Throw all the vertex info for a frame's worth of text into a single VBO
  3. Draw all your strings for the frame with a single glDrawArrays() call


来源:https://stackoverflow.com/questions/31817526/speed-up-text-rendering-performance-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!