2

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

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 中找不到有用的信息。

任何帮助将不胜感激!

4

3 回答 3

2

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

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

于 2012-10-22T00:38:05.717 回答
1

与其逐个字形地进行,为什么不在软件中一次将整个字符串渲染为单个位图,然后将其渲染为单个纹理?由于文本在最初显示后通常不会频繁更改,因此您可以在首次显示时按需渲染有问题的字符串,然后将字符串的纹理保留在 GPU 中,直到它离开屏幕。

于 2012-10-21T12:42:42.023 回答
1

明显的改进是不预先渲染所有 50.000+ Unicode 字符。你真的需要中文吗?取而代之的是,使FontFace能够根据需要动态地对字符进行 blitting,并且最初只 blit U+0020 - U+007E(ASCII)。

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

于 2012-10-21T12:52:16.097 回答