воскресенье, 12 февраля 2012 г.

Всем доброго дня.
Сегодня, как я и обещал, веду свой рассказ о новой системе отрисовки шрифтов в quad-engine. Система пока еще не внедрена, но уже протестирована и будет встроена в следующей же публичной версии. Ничего нового придумано не было, это всего лишь метод distance field. Однако, как показала практика, многие о нем не знают и даже не догадываются. Самое занятное в этом методе, то, что для его реализации вовсе ненужны шейдеры, этот метод можно реализовать обычным альфа-тестированием, не теряя при этом скорости ни капли.
Давайте перейдем к тому, как это работает.

Самое сложное в отрисовке глифов методом distance field это генерация исходной текстуры. Для этого берется глиф высокого разрешения, например:
Далее выбирается размер текстуры, который будет сгенерирован для этого глифа, разумеется существенно меньшего размера. И для каждой точки исходного изображения в текстуре берется эквивалентная точка. Для нее по исходному изображению считается дистанция до ближайшей точки другого цвета (тоесть границы) и записывается в текстуру следующим образом:
Если у нас прозрачный цвет (тут белый), то дистанция до черного шифруется как 0..128, где 128 это нулевая дистанция, тоесть ребро.
Если прозрачность ненулевая, (тут черный). то чем дальше до белого пикселя, тем больше значение в пределах от 128..255
В итоге мы получаем такую текстурку:

Маленькая и скромненькая, но она позволит нарисовать нам глиф, схожий по размерам с исходным и не о с очень большими искажениями. Загружаем текстурку и рендерим ее, скажем, с 400% увеличением (и билинейной фильтрацией). Получаем, ожидаемо, что-то вроде этого:
Печальное зрелище. Такой картинкой много текста не отрендеришь. Оговорюсь что это отображение альфаканала. РГБ канал содержит чисто белый цвет. Далее мы включаем альфа-тестирование, где устанавливаем значение 0.5 (или 128), тоесть от картинки осечется всё, что меньше 128 по альфе. Тут нам поможет аппаратная особенность билинейной фильтрации, а именно то, что видеокарта интерполирует все значения, и делает нам градиенты, тем самым как бы восстанавливая часть утерянных значений.
Результатом такой отрисовки будет такая картинка:
Тут надо отметить, что в моем случае вывод идет через простейший шейдер, что позволило мне сделать по контуру глифа антиалиасинг. Еще раз напомню, что это отрендеренно из той мелкой текстурки с увеличением в 400%.
При увеличениях до 200% искажений и неровностей по контуру глифа нет вообще, так что шрифт можно использовать в довольно большом диапазоне увеличений, не задумываясь о том, что он "поплывёт" и размутнится.

Данная технология разработана и используется компанией Valve в игре Team Fortress 2. Больше подробностей (на английском) можно прочитать в приведенной выше ссылке. В частности, с помощью такого подхода к глифам можно добавлять антиалиасинг, обводку, свечение, тени и прочее.

8 комментариев:

  1. Попробуй генерировать DF из большой текстурки (4,8 раз больше той, которую хочешь получить). Результат тебе понравится. Искажений будет намного меньше.

    ОтветитьУдалить
  2. Ага, это спасибо, но тут совсем тестовые были значения, я уже оптимизировал, и увеличение работает уже до 1000% от размера df текстурки.
    ЗЫ: не знал что ты читаешь мой блог.

    ОтветитьУдалить
  3. Заглядываю изредка) Каждый глиф в отдельности обрабатываешь? Не медленно получается. 1024x1024 с увеличением в 10 раз * сложность алгоритма для DF это много) В общем хотелось бы глянуть и сравнить со своей реализацией..

    ОтветитьУдалить
  4. Как только реализую, сразу же отпишусь с примерами.

    ОтветитьУдалить
  5. Заделюсь интересной ссылкой: http://labs.qt.nokia.com/2011/07/15/text-rendering-in-the-qml-scene-graph/ А интересен там абзац про sub pixel aa

    ОтветитьУдалить
  6. Я помнится делал на канвасе субпиксельный рендеринг шрифта с чем-то вроде ClearType :) Идея, конечно, заманчивая, но в играх явно лишенная смысла, кроме случаев, если ты делаешь книгу, рпг... незнаю, что-то где очень много текста.
    К тому же в идеале надо учесть, что матрицы бывают не только RGB, но и BGR. А про CRT мониторы я вообще промолчу, такой рендеринг только ухудшит восприятие цвета на них. так что увы.

    ОтветитьУдалить
  7. Знаем, знаем) Я думал брать настройки из системы, но пока даже не шупал эту тему.

    ОтветитьУдалить
  8. Бывало (и не раз), что настройки у человека были сделаны наоборот. Ему казалось что так лучше, а было (ясное дело) только хуже. Вообщем это сложнее чем просто АА втопить.

    ОтветитьУдалить