Улучшенный текст качества в WebGL

Я ищу метод для получения лучшего качества (произвольного) текста внутри WebGL. В настоящее время я использую рендеринг растровых изображений на двумерном холсте и blitting их в контексте WebGL.

Этот метод описан здесь http://delphic.me.uk/webgltext.html

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

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

Итак, как создать текст лучшего качества в WebGL? Существуют ли методы извлечения текстовых фигур в Javascript для улучшения качества?

Ответ 1

Поработав со шрифтами в течение некоторого времени, я вижу 6 способов сделать шрифты в WebGL, все с преимуществами и недостатками:


Шрифт как геометрия

  1. Получите шрифт с открытым исходным кодом, как у Google (Open Sans и Roboto очень популярны)
  2. Считайте кривые шрифта, используя OpenType или аналогичный (https://nodebox.github.io/opentype.js/)
  3. Триангулируйте кривые персонажей. Мой фаворит для этого - Earcut, поскольку это очень быстро https://github.com/mapbox/earcut
  4. Нарисуйте полигоны для каждого символа как обычные треугольники WebGL.

преимущества

  • Очень быстро, если у вас много текста и вам нужны полнофункциональные шрифты, это ваш лучший выбор. Масштабирование шрифта выполняется на графическом процессоре с помощью матричных операций.

Недостатки

  • Качество отображаемого шрифта зависит от сглаживания, включенного вашим браузером WebGL. Safari выполняет 8x8 AA, что выглядит неплохо, но все остальные браузеры используют только 4x4, которые могут выглядеть блочными. Кроме того, мобильный браузер вообще не включает AA, что делает шрифты очень мобильными на ваших мобильных устройствах.

холст

Это также называется "Динамические текстуры по запросу". Отобразите только текстовые глифы на (закадровый) холст и перетащите его на экран в виде текстуры WebGL, как описано здесь: http://delphic.me.uk/webgltext.html

преимущества

  • Достойное качество.

Недостатки

  • Скорость, в зависимости от того, сколько текста вам нужно отрендерить, в какое время это может работать нормально. Особенно, если вам нужно только визуализировать статический текст.

В игре Age of Empires III используется этот метод.


Растровые шрифты

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

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

Преимущества:

  • Просто понять
  • Тривиально создать текстурный атлас
  • Можно использовать цветные шрифты

Недостатки

  • Выглядит ужасно размыто при увеличении
  • Необходимо предварительно отрендерить все глифы, которые используются
  • Требуется текстура для размера шрифта
  • Для оптимального использования текстуры требуется упаковка текстурных бинов. пример

Шрифты поля с подписью

Крис Грин из Valve написал "книгу" об использовании полей со знаком расстояния для текстур. Вы захотите прочитать документ SIGGRAPH 2007 года "Улучшенное альфа-тестирование увеличения для векторных текстур и спецэффектов".

Обычно атлас текстуры шрифта выглядит следующим образом. Текстура SDF выглядит так. Да, текстурный атлас SDF выглядит размытым, когда отображается "как есть". Это потому, что 8-битный канал был закодирован как:

  • 0 → -1.0 (снаружи)
  • 255 → +1.0 (внутри)

Преимущества:

  • Можно использовать одну текстуру для масштабирования шрифтов от очень маленьких (6 пикселей) до очень больших (200 px+) без потери качества,
  • Сглаживание часто бывает "бесплатно".

Недостатки:

  • Необходимо предварительно отрендерить все используемые глифы,
  • Предварительная обработка текстуры SDF обычно выполняется в автономном режиме из-за предварительной обработки SLOW (~ 15 секунд),
  • Не многие люди понимают, как создать качественное сглаживание. Такие хаки, как smoothstep() и fwidth() дают результаты с плохим качеством из-за того, что люди интерполируют текстурное пространство вместо экранного. Также не помогает то, что WebGL fwidth() использует неправильную константу.
  • Одноканальный SDF не сохраняет края, как намекает Valve в своей статье. Их решение состояло в том, чтобы использовать многоканальный SDF, но не предоставило никаких деталей. См. Магистерскую диссертацию Виктора Хлумского или его открытый исходный код.
  • Требуется "заполнение ячейки" или граница в несколько пикселей, если шрифты SDF используются в небольших размерах.
  • Поддерживаются только монохромные шрифты

Тем не менее, если у вас есть несколько шрифтов, то SDF-шрифты могут быть огромным выигрышем как по размеру (нужно только 1), так и по качеству (выглядит фантастически как при малых, так и при больших размерах)

Как создавать SDF-текстуры

Теперь есть простой в использовании модуль npm, который генерирует текстуры и метаданные SDF, доступные здесь.


SDF Demos


Шрифты на GPU

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

В этом блоге есть сводка визуализации шрифтов по состоянию на февраль 2017 года.

преимущества

  • Глифы высокого качества при нормальных и больших размерах

Недостатки

  • Высокая стоимость и сложность шейдеров
  • Имеет проблемы с качеством при небольших размерах

Демонстрация шрифтов графического процессора


Холст наложение

Для моего текущего проекта я использую 2D-холст HTML5 для рендеринга текста и других 2D-примитивов и накладываю его, используя прозрачность поверх холста WebgGL. Я был удивлен полученной скоростью, она превосходит все остальные описанные здесь методы по скорости и качеству очень хорошо.

Пока ваш текст статический 2D и вам не нужны никакие 3D преобразования, я бы рекомендовал это. В моем проекте это примерно в 2 раза быстрее, чем в предыдущем методе (Font as Geometry).

Ответ 2

Глядя на исходный код для three.js, вы можете найти решение.

Вот код для создания шрифта three.js https://github.com/mrdoob/three.js/blob/master/src/extras/FontUtils.js

Он говорит в верхней части

 * For Text operations in three.js (See TextGeometry)
 *
 * It uses techniques used in:
 *
 *  typeface.js and canvastext
 *      For converting fonts and rendering with javascript
 *      http://typeface.neocracy.org
 *
 *  Triangulation ported from AS3
 *      Simple Polygon Triangulation
 *      http://actionsnippet.com/?p=1462
 *
 *  A Method to triangulate shapes with holes
 *      http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/

Typeface.js предоставляет данные шрифта, а также онлайн-форму для преобразования шрифтов TrueType.

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

  • Извлеките текст в растровые изображения и более высокое разрешение и нарисуйте их с разрешением или меньше.

  • Используйте средство рендеринга кривой. (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html)

Ответ 3

Pixi.js соглашается с рекомендацией выше для SDF.

https://github.com/PixelsCommander/pixi-sdf-text

Они говорят (и они отличный игровой проект для браузера)

SDF - самый эффективный способ рисования текста в WebGL. Он использует особый вид растровых атласов и GLSL-шейдеров, чтобы рисовать масштабируемый вектором текст очень наглядно на GPU.

И это было из MapBox, который, по крайней мере, сделал это тоже в какой-то момент.