文字渲染非常慢

Pio*_*cki 9 c++ opengl performance ftgl

我正在使用FTGL库来渲染我的C++,OpenGL应用程序中的文本,但我发现它非常慢,尽管它据说是快速而有效的库.

即使对于少量文本,性能下降也是可见的,但是当我尝试渲染几行文本时,FPS从350减少到30~:

在此输入图像描述

是的,我已经知道FPS不是检查效率的好方法,但在这种情况下应该没有那么大的差异.

我发现了一个允许我在内部使FTGL使用显示列表以提高速度的功能,但它默认情况下似乎已打开.无论如何,我尝试使用它,但它没有给我任何东西.所以我认为它可能已经被腐蚀了,或者我不太了解它,所以我决定将渲染文本放到我自己的显示列表中,但是差异要么太小,以至于我甚至看不到它,或者没有区别.

bool TFontManager::renderWrappedText(font_ptr font, int lineLength, const TPoint& position, const std::string& text) {
    if(font == nullptr) {
        return false;
    }

    string key = sizeToString(font->FaceSize());    // key to look for it in map
    key.append(TUtil::intToString(lineLength));
    key.append(text);
    GLuint displayListId = getDisplayListId(key);   // get display list id from internal map

    if(displayListId != 0) {                        // if display list id was found in map, i can call it
        glCallList(displayListId);
        return true;
    }

    // if id was not found, i'm creating new display list 

    FTSimpleLayout simpleLayout;
    simpleLayout.SetLineLength((float)lineLength);

    simpleLayout.SetFont(font.get());

    displayListId = glGenLists(1);
    glNewList(displayListId, GL_COMPILE);

    glPushMatrix();
    glTranslatef(position.x, position.y, 0.0f);
    simpleLayout.Render(TUtil::stringToWString(text).c_str(), -1, FTPoint(), FTGL::RENDER_FRONT | FTGL::RENDER_BACK);        // according to visual studio's profiler, bottleneck is inside this function. more exactly in drawing textured quads when i looked into FTGL code.
    glPopMatrix();

    glEndList();

    m_textDisplayLists[key] = displayListId;

    glCallList(displayListId);

    return true;
}
Run Code Online (Sandbox Code Playgroud)

我在调试模式下检查了断点 - 它只创建一次显示列表,之后它只调用以前创建的一个.

这种缓慢渲染的原因可能是什么?我怎么能加快速度呢?

编辑: 我正在使用FTTextureFont(每个字形使用一个纹理).根据这个 FTGL教程,我宁愿使用FTBufferFont,因为它每行只使用一个纹理.缓冲区字体应该更快,但在我尝试之后它更加丑陋甚至更慢(6 fps而纹理字体给了我30 fps).

EDIT2:

这就是我创建字体的方式:

font_ptr TFontManager::getFont(const std::string& filename, int size) {
    string fontKey = filename;
    fontKey.append(sizeToString(size));

    FontIter result = fonts.find(fontKey);
    if(result != fonts.end()) {
        return result->second;      // Found font in list
    }

    // If font wasn't found, create a new one and store it in list of fonts

    font_ptr font(new FTTextureFont(filename.c_str()));
    font->UseDisplayList(true);

    if(font->Error()) {
        string message = "Failed to open font";
        message.append(filename);
        TError::showMessage(message);
        return nullptr;
    }

    if(!font->FaceSize(size)) {
        string message = "Failed to set font size";
        TError::showMessage(message);
        return nullptr;
    }

    fonts[fontKey] = font;

    return font;
}
Run Code Online (Sandbox Code Playgroud)

EDIT3:

这是从FTGL库源代码中获取的函数,该源代码呈现字形FTTextureFont.它对单独的字形使用相同的纹理,只使用其他坐标,所以这不应该是一个问题.

const FTPoint& FTTextureGlyphImpl::RenderImpl(const FTPoint& pen,
                                              int renderMode)
{
    float dx, dy;

    if(activeTextureID != glTextureID)
    {
        glBindTexture(GL_TEXTURE_2D, (GLuint)glTextureID);
        activeTextureID = glTextureID;
    }

    dx = floor(pen.Xf() + corner.Xf());
    dy = floor(pen.Yf() + corner.Yf());

    glBegin(GL_QUADS);
        glTexCoord2f(uv[0].Xf(), uv[0].Yf());
        glVertex2f(dx, dy);

        glTexCoord2f(uv[0].Xf(), uv[1].Yf());
        glVertex2f(dx, dy - destHeight);

        glTexCoord2f(uv[1].Xf(), uv[1].Yf());
        glVertex2f(dx + destWidth, dy - destHeight);

        glTexCoord2f(uv[1].Xf(), uv[0].Yf());
        glVertex2f(dx + destWidth, dy);
    glEnd();

    return advance;
}
Run Code Online (Sandbox Code Playgroud)

CJJ*_*CJJ 3

从普通字体文件渲染版式是一项计算量相当大的操作。字体字形被读取为一组样条线,用于生成字符边界,这些边界被细分并馈送到图形管道中。我对 FreeType2 不太熟悉,但我使用过 FTGL。您应该使用 FontAtlas 来呈现类型。FontAtlas 是一个常规纹理图集(很像精灵表),它针对每个字体大小渲染一次,然后存储以供将来的字形渲染。

有关该过程的更多信息,请查看此链接: http://antongerdelan.net/opengl4/freetypefonts.html

这应该会大大提高性能。尽管您可能会失去一些字体渲染的灵活性。