Как я могу управлять текстурой кеша в OpenGL? - PullRequest
3 голосов
/ 27 марта 2009

Я пишу текстовый рендерер для приложения OpenGL. Размер, цвет, грань шрифта и сглаживание могут быть изменены во время выполнения (и, таким образом, несколько шрифтовых граней могут появляться на экране одновременно). Слишком много комбинаций, чтобы выделить одну текстуру для каждой комбинации строки и атрибутов. Однако в любой момент времени на экране будет отображаться только небольшое подмножество всей базы данных строк.

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

Итак, передо мной текстура 2048x2048, в которую я могу помещать любые строки, которые могу вписать, так как они запрашиваются приложением для целей кэширования. Я быстро понял, что отслеживание свободного пространства, доступного в двухмерном пространстве, не тривиально.

Я смотрел на такие вещи, как Best Fit и Next fit, но, похоже, они подходят для 1d пробелов.

Как мне управлять этой текстурой кеша в OpenGL?

Редактировать: С тех пор я узнал, что это пример "проблемы с 2d упаковкой".

Ответы [ 3 ]

2 голосов
/ 27 марта 2009

У вас проблема с упаковкой в ​​мусорное ведро.

Сначала плохие новости: это сложно для NP, поэтому стоит найти оптимальное решение.

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

В случае, если я получил глифы, которые больше, чем один из моих блоков сетки, я просто выделил два или более блоков, используя поиск методом грубой силы (это случалось не так часто). В случае, если я не нашел подходящего блока, я просто удалил несколько символов из кэша, чтобы освободить место.

Это было гораздо проще, чем хранить вещи в последнем использованном кеше и работать почти так же хорошо.

Кстати - у вас всегда будет какая-то трата памяти на текстуры для такого кэша. Если только у вас очень нехватка памяти, это не должно быть проблемой. Вы должны использовать небольшой текстурный формат (8-битная альфа хорошо работает для шрифтов).

Также: если вы сделаете ваши сеточные блоки кратными 8 пикселям, и вы можете уменьшить сглаживание до 4 битов, вы можете сжать глифы в один из сжатых форматов DXT или S3TC на лету. Таким образом, потраченное впустую пространство текстур перестает быть проблемой.

1 голос
/ 15 июля 2012

Если у вас недостаточно текстурной памяти, вы можете взглянуть на технику рендеринга шрифтов «Поле расстояния» или «Поле расстояния со знаком». Вы можете использовать 512x512 текстур для каждого семейства шрифтов, и вы можете визуализировать идеально сглаженный текст любого размера.

Для этого алгоритма вам нужно сгенерировать специальную текстуру, которая содержит расстояние от текселя до края текстуры. Взгляните на оригинальную статью ребят из Valve: http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf. Есть некоторые рамки, которые используют это. Например, последняя версия Qt использует поле расстояния со знаком для визуализации текста.

0 голосов
/ 31 марта 2009

Я решил использовать простой подход. Разделите текстуру на строки переменной высоты. Первая текстура, которая будет размещена в строке, определяет высоту строки. Если текстура может вписаться в существующую строку по высоте, проверьте, достаточно ли остальной ширины, и поместите ее туда. В противном случае начните новый ряд. Если новая строка не может быть запущена, не кэшируйте строку.

...