商业游戏如何处理动态字体加载?

时间:2012-10-21 11:33:29

标签: c++ fonts directx freetype direct3d11

这就是我在伪代码中处理字体渲染的方法(简化):

FontFace* CreateFontFace(fontName, fontSize)
{
    FontFace* fontFace = LoadFromDiskCache(fontName, fontSize);
    if ( fontFace == 0 )
    {
        for(each glyph)
        {
            Load glyph using FreeType;
            Load its size and metric;
        }
        Pack all glyph bitmaps to a single UV-atlas
        {
            Calculate rectangles (RectangleBinPack); // Very slow!
            Blit glyphs to UV-atlas; // Slow!
            Insert rectangles to std::vector; // UV-dictionary;
            Insert metrics to std::vector;
        }
        Wrap it all to a struct FontFace;
        AddToDiskCache(fontName, fontSize); 
        // so on next startup it will be cached on HDD 
    }
    return fontFace;
}


bool OnInit(fontName, fontSize)
{
    for (each fontName)
    {
        for (each fontSize)
        {
            FontFace* fontFace = CreateFontFace(fontName, fontSize));
            Insert fontFace to container based on std::map;
        }
    }
}

void OnSomtimes(FontFace, pDevice)
{
    On demand create texture from FontFace.uvatlas on pDevice;
}

void OnRender(wstring, FontFace)
{
    if(needUpdate)
    {
        // Generate std::vector<Sprite> using given FontFace
        sprites = CreateSprites(wstring, FontFace);
    }

    Draw all vector<Sprite> at once with my SpriteBatch object; 
    // Big dynamic VertexBuffer, Instancing or GeometryShader 
    // depending on hardware caps
}

所以我可以缓存一些最常用的字体,甚至是所有曾经使用过的游戏字体。 但在某些应用程序中,用户可以选择另一种应用程序以前从未见过的字体/大小/样式,并立即应用。或者,例如,在一些游戏中,用户可以替换游戏文件夹中的“font.tff”文件,并且游戏将在启动时以多种尺寸/样式和数千个Unicode字符中的每一个使用它,而无需额外的时间预加载。奇迹!

我需要这样的东西 - 即时加载字体。

当然,我可以根据需要单独加载字形,并按字形呈现字形,但这意味着没有批处理,每帧的Draw调用和巨大的GPU带宽。不确定它对OpenGL是否正常,但它不适用于D3D11。

他们如何在游戏工作室中这样做?也许你知道一种不同的方法?我听说过将字体渲染为几何,GPU处理和复杂的曲线算法,但在google中找不到有用的信息。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

游戏中的字体渲染通常是从包含在编译/离线时生成的所有字形的位图完成的。您可以使用像AngelCode BMFont这样的位图字体生成器,它非常易于使用并且非常适合游戏,因为它支持更加GPU带宽友好的DXTx压缩位图。

对于高分辨率字体,Alpha Texted Magnification技术目前是游戏中的首选技术,主要是在渲染贴花时。

答案 1 :(得分:1)

为什么不在软件中将整个字符串全部渲染为单个位图,而只是将其渲染为单个纹理?由于文本在最初显示时通常不会经常变化,因此您可以在首次显示时按需渲染字符串,然后将字符串的纹理保留在GPU中,直到它离开屏幕。

答案 2 :(得分:1)

显而易见的改进是不预先渲染所有50.000+ Unicode字符。你真的需要中文吗?相反,让FontFace能够根据需要动态地设置字符,最初只是U+0020 - U+007E(ASCII)。

一个稍微聪明的解决方案可能是在您需要第一个时从脚​​本中呈现所有字符。毕竟,如果你需要一个泰国角色,你可能需要更多。但这显然需要一些额外的表来对Unicode字符进行分组。