加快文本渲染性能openGL - 继续

时间:2015-08-12 16:56:10

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

我最近发布了一个问题here,我做了adviced me by @genpfault(感谢您:])。问题是,我的字体仍然花费很长时间来绘制

我将所有字体顶点和texcoords存储在一个std::vector容器中,颜色存储在另一个std::vector中,然后使用VBO(在流模式下)绘制它。

我正在收集当前帧的数据,如下所示:

void CFreeType::RenderText(std::string text, int posX, int posY, Vector3d color)
{
    std::string::const_iterator c;
    for(c = text.begin(); c != text.end(); c++)
    {
        //Load character from map
        Character ch = Characters[*c];

        /*I know it's embarrassing, but I don't know, how can I use  
        only one Colors.push_back(newColor); so it applies to one face.  
        Right now I have to color each vertex. I guess it can be set somewhere in VBO*/  

        Vert_and_TexCoords.push_back(Vec4f(xpos, ypos, ch.texCoordOffset.x, ch.texCoordOffset.y));
        Colors.push_back(newColor);

        Vert_and_TexCoords.push_back(Vec4f(xpos, ypos + ch.Size.y, ch.texCoordOffset.x, ch.texCoordOffset2.y));
        Colors.push_back(newColor);

        Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos + ch.Size.y, ch.texCoordOffset2.x, ch.texCoordOffset2.y));
        Colors.push_back(newColor);

        Vert_and_TexCoords.push_back(Vec4f(xpos, ypos, ch.texCoordOffset.x, ch.texCoordOffset.y));
        Colors.push_back(newColor);

        Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos + ch.Size.y, ch.texCoordOffset2.x, ch.texCoordOffset2.y));
        Colors.push_back(newColor);

        Vert_and_TexCoords.push_back(Vec4f(xpos + ch.Size.x, ypos, ch.texCoordOffset2.x, ch.texCoordOffset.y));
        Colors.push_back(newColor);
    }
}

这是我的绘图功能:

void CFreeType::TextPopBack()
{
    textShader->Use();

    //Bind VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f) + Colors.size() * sizeof(Color3f), 0,  GL_STREAM_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, Vert_and_TexCoords.size() * sizeof(Vec4f), Vert_and_TexCoords.data());
    glBufferSubData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f), Colors.size() * sizeof(Color3f), Colors.data());

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(Vert_and_TexCoords.size() * sizeof(Vec4f)));

    glDrawArrays(GL_TRIANGLES, 0, Vert_and_TexCoords.size());

    //Unbind VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    textShader->StopShader();
    Vert_and_TexCoords.clear();
    Colors.clear();
}

我想让文本呈现灵活,所以静态VBO缓冲区大小不是很好的方法 此外,文本着色不是以我在代码注释中注意到的最佳方式完成的,但我希望能够使用用户指定的颜色为每个字母着色。

着色器很好,我希望。如果有人有兴趣,我会发布它们 现在需要大约40毫秒才能呈现 400个字母

编辑:正如你们建议只在VBO缓冲区中分配大量数据并用glBufferSubData填充VBO一样,我试了一下,没有任何改变。我和以前一样 我有一个分配std::vector的空间的想法,但它也没有帮助。

1 个答案:

答案 0 :(得分:0)

我看到的一个问题是你为每个呈现的帧执行此操作:

glBufferData(GL_ARRAY_BUFFER, Vert_and_TexCoords.size() * sizeof(Vec4f) + Colors.size() * sizeof(Color3f), 0,  GL_STREAM_DRAW);

每次渲染时都要分配内存。根据给定的信息,我假设您这样做是因为每次渲染文本时文本的数量都会发生变化。我不是每帧都分配这个,而是尝试创建一个更大的固定缓冲区,并使用glbuffersubdata()来填充所需的位。我认为这应该比每帧重新分配缓冲区更快。这只是您可以尝试的一种优化。

编辑:我的另一个建议是,不是每个字符发送3个浮点数作为1种颜色,也许你应该使用颜色索引。伪代码示例:

Color 1 = 1.0f, 0.0f, 0.0f // red
Color 2 = 0.0f, 1.0f, 0.0f // green
// Text format = [color index] [character] ... and so on
String = 2 'a' 1 'b' 1 'c' 2 'd'
This will render 'a' and 'd' as green; and 'b'/'c' will be rendered as red.

然后,您的片段着色器将使用颜色索引根据索引在字符中着色。这将是一个非常小的优化,这将使您的代码更复杂。但它会显着减小缓冲区的大小。这也可以帮助您提高性能