Как коммерческие игры справляются с загрузкой шрифтов на лету?

Вот как я обрабатываю рендеринг шрифта в псевдокоде (упрощенно):

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 на кадр и огромная пропускная способность графического процессора. Не уверен, что он в порядке или нет для OpenGL, но не подходит для D3D11.

Как они это делают в игровых студиях? Может быть, вы знаете другой подход? Я слышал о рендеринге шрифтов как геометрии, графической обработке и сложных алгоритмах кривых, но не могу найти полезную информацию в Google.

Любая помощь будет оценена!

2

Решение

Рендеринг шрифтов в играх обычно выполняется из растрового изображения, которое содержит все глифы, сгенерированные во время компиляции / офлайн. Вы можете использовать генератор растровых шрифтов, как AngelCode BMFont который действительно прост в использовании и хорошо подходит для игр, поскольку поддерживает сжатые растровые изображения DXTx, которые более дружественны к пропускной способности графического процессора.

Для высокого разрешения шрифта, Альфа текстовое увеличение Техника в настоящее время является предпочтительной техникой в ​​играх, в основном при рендеринге надписей.

2

Другие решения

Вместо того, чтобы делать это глиф за глифом, почему бы не отобразить всю строку сразу в программном обеспечении в виде единого растрового изображения, а затем просто отобразить ее как единую текстуру? Поскольку текст, как правило, изменяется не очень часто после первоначального отображения, вы можете отображать строку по запросу при первом ее отображении, а затем сохранять текстуру строки в графическом процессоре до тех пор, пока она не выйдет за пределы экрана.

1

Очевидное улучшение состоит в том, чтобы не отображать все 50.000+ символов Unicode заранее. Тебе действительно нужен китайский? Вместо этого сделайте FontFace способен бить персонажей на лету по мере необходимости, и изначально блит просто U+0020 - U+007E (ASCII).

Немного более разумным решением может быть рендеринг всех символов из скрипта всякий раз, когда вам нужен первый. В конце концов, если вам нужен один тайский персонаж, вам, вероятно, понадобится больше их. Но это, очевидно, требует некоторых дополнительных таблиц для группировки символов Unicode.

1
По вопросам рекламы [email protected]