2013-03-21 191 views
9

我正在使用FTGL庫在我的C++,OpenGL應用程序中渲染文本,但我覺得它非常慢,儘管它據說是快速高效的庫。文字渲染非常緩慢

即使是少量的文本,性能下降是可見的,但是當我嘗試呈現的幾行文字,FPS下降350〜30〜:

enter image description here

是的,我已經知道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; 
} 

我在調試模式下斷點檢查 - 它會創建顯示列表中只有一次,以後只調用之前創建的。

這麼慢的渲染可能是什麼原因?我該如何加快速度?

編輯︰ 我使用FTTextureFont(它使用每個字形一個紋理)。根據this 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; 
} 

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; 
} 
+0

您應該可以將文本渲染爲紋理,並且只在文本更改時更新紋理。當然,如果文本每幀改變一次,這都無濟於事。 – didierc 2013-03-21 10:29:41

+0

@didierc我認爲這就是FTGL已經做到的。 – 2013-03-21 11:20:53

+0

我們使用FTGL和'FTTextureFont',我們獲得了良好的性能。你一定在做錯事。 – user763305 2013-03-21 11:49:22

回答

2

從正常字體文件渲染排版是一個相當計算密集的操作。字體字形被讀取爲一組樣條,用於生成鑲嵌並饋送到圖形管道中的字符邊界。我對FreeType2並不十分熟悉,但我已經使用了FTGL。你應該使用FontAtlas來渲染類型。 FontAtlas是一個常規的紋理地圖集(很像精靈圖紙),每個字體大小渲染一次,然後存儲爲未來的字形渲染。

看看這個鏈接獲取更多信息的過程: http://antongerdelan.net/opengl4/freetypefonts.html

這將極大地提高性能。儘管你可能會失去一些字體渲染的靈活性。

+0

非常感謝您的答覆和鏈接 - 它似乎非常有用。這絕對不是我想聽到的答案,因爲我非常喜歡FTGL功能,但似乎我沒有任何其他選擇。 – 2013-03-25 06:31:35