Подтвердить что ты не робот

Что представляет собой современное состояние для текстового рендеринга в OpenGL с версии 4.1?

В OpenGL уже есть ряд вопросов о текстовом рендеринге, например:

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

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

Каков рекомендуемый подход для текстового рендеринга с использованием современного OpenGL? (Сопоставление существующего программного обеспечения с использованием подхода является хорошим доказательством того, что он хорошо работает)

  • Геометрические шейдеры, которые принимают, например. положение и ориентацию и последовательность символов и испускать текстурированные квадратики.
  • Геометрические шейдеры, которые отображают векторные шрифты
  • Как указано выше, но вместо этого используйте тесселяционные шейдеры
  • Вычислительный шейдер для создания растеризации шрифтов
4b9b3361

Ответ 1

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

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

Смотрите знаменитую бумагу Valve для техники.

Техника концептуально схожа с тем, как работают неявные поверхности (метаболлы и т.д.), Хотя она не генерирует многоугольники. Он полностью выполняется в пиксельном шейдере и принимает расстояние, выбранное из текстуры, как функцию расстояния. Все, что выше выбранного порога (обычно 0,5), находится "внутри", все остальное "вне". В простейшем случае на 10-летнем оборудовании, не поддерживающем шейдеры, установка порога альфа-теста на 0,5 будет делать именно это (хотя и без специальных эффектов и сглаживания).
Если кто-то хочет добавить немного больше веса к шрифту (искусственно выделенный жирным шрифтом), то немного меньшее пороговое значение сделает свое дело без изменения одной строки кода (просто измените форму "font_weight"). Для эффекта свечения каждый просто рассматривает все, что выше одного порога, как "внутри", а все, что выше другого (меньшего) порога, как "снаружи, но в сиянии", и LERP между ними. Сглаживание работает аналогично.

Используя 8-битное значение расстояния со знаком, а не один бит, этот метод увеличивает эффективное разрешение вашей карты текстуры в 16 раз в каждом измерении (вместо черного и белого используются все возможные оттенки, таким образом, мы имеем 256-кратное увеличение информация, использующая то же хранилище). Но даже если вы увеличите намного больше 16x, результат все равно выглядит вполне приемлемым. Длинные прямые линии со временем станут немного волнистыми, но типичных "блочных" артефактов сэмплирования не будет.

Вы можете использовать геометрический шейдер для генерации квадраторов из точек (уменьшить пропускную способность шины), но, честно говоря, выигрыши довольно незначительны. То же самое верно для рендеринга инстансированных символов, как описано в GPG8. Затраты на инстансинг амортизируются, только если у вас много текста для рисования. Преимущества, на мой взгляд, никак не связаны с дополнительной сложностью и возможностью снижения рейтинга. Кроме того, вы либо ограничены количеством константных регистров, либо должны считывать данные из объекта буфера текстур, что неоптимально для согласованности кэша (и целью было оптимизировать с самого начала!).
Простой, простой старый буфер вершин будет таким же быстрым (возможно, быстрее), если вы запланируете загрузку немного раньше времени, и будет работать на каждом оборудовании, созданном за последние 15 лет. И это не ограничивается каким-либо конкретным количеством символов в вашем шрифте или определенным количеством символов для визуализации.

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

Есть удобный инструмент Джонатана Даммера для создания текстур расстояний: страница описания

Обновить:
Как было недавно отмечено в Программируемом извлечении вершин (D. Rákos, "OpenGL Insights", стр. 239), нет существенной дополнительной задержки или накладных расходов, связанных с программным извлечением данных вершин из шейдера на новейших поколениях графических процессоров, по сравнению с делать то же самое с помощью стандартной фиксированной функции.
Кроме того, последние поколения графических процессоров имеют все больше и больше разумных размеров кэш-памяти L2 общего назначения (например, 1536 кБ на nvidia Kepler), поэтому можно ожидать, что проблема некогерентного доступа при вытягивании случайных смещений для четырехугольных углов из текстуры буфера будет меньше проблема.

Это делает идею извлечения постоянных данных (таких как размеры квадратов) из буферной текстуры более привлекательной. Таким образом, гипотетическая реализация может сократить до минимума передачи PCIe и памяти, а также памяти графического процессора при таком подходе:

  • Загружайте только символьный индекс (по одному на отображаемый символ) в качестве единственного ввода в вершинный шейдер, который передает этот индекс и gl_VertexID, и gl_VertexID до 4 точек в геометрическом шейдере, gl_VertexID при этом индекс символа и идентификатор вершины ( это будет "gl_primitiveID, сделанный доступным в вершинном шейдере") как единственные атрибуты, и захватить это через обратную связь преобразования.
  • Это будет быстро, потому что есть только два выходных атрибута (основное узкое место в GS), и он близок к "no-op" в противном случае на обоих этапах.
  • Свяжите текстуру буфера, которая содержит для каждого символа в шрифте текстурированные положения вершин четырехугольника относительно базовой точки (это в основном "метрики шрифта"). Эти данные могут быть сжаты до 4-х чисел на квад, сохраняя только смещение нижней левой вершины и кодируя ширину и высоту выровненного по оси блока (если предположить, что половина поплавка, это будет 8 байтов постоянного буфера на символ - типичный 256-символьный шрифт может полностью уместиться в 2 кбайт кеша L1).
  • Установите форму для базовой линии
  • Привязать текстуру буфера с горизонтальными смещениями. Вероятно, их можно даже рассчитать на графическом процессоре, но это гораздо проще и эффективнее для подобных вещей на процессоре, поскольку это строго последовательная операция, а вовсе не тривиальная (вспомним кернинг). Кроме того, потребуется еще один проход обратной связи, который станет еще одной точкой синхронизации.
  • Визуализируйте ранее сгенерированные данные из буфера обратной связи, вершинный шейдер извлекает горизонтальное смещение базовой точки и смещения угловых вершин из объектов буфера (используя идентификатор примитива и индекс символа). Исходный идентификатор вершины представленных вершин теперь является нашим "примитивным идентификатором" (помните, что GS превратил вершины в квадраты).

Таким образом, в идеале можно уменьшить требуемую ширину полосы вершины на 75% (амортизироваться), хотя она сможет отображать только одну строку. Если бы кто-то хотел иметь возможность визуализировать несколько линий за один вызов отрисовки, ему нужно было бы добавить базовую линию к текстуре буфера, а не использовать униформу (уменьшая прирост пропускной способности).

Однако, даже если предположить, что сокращение на 75% - поскольку данные вершин для отображения "разумного" объема текста - всего где-то около 50–100 кБ (что практически равно нулю для графического процессора или шины PCIe) - я все еще сомневаюсь, что добавленное сложность и потеря обратной совместимости действительно стоят того. Уменьшение нуля на 75% все еще только ноль. По общему признанию, я не пробовал вышеупомянутый подход, и необходимы дополнительные исследования, чтобы сделать действительно квалифицированное утверждение. Но тем не менее, если кто-то не сможет продемонстрировать действительно ошеломляющую разницу в производительности (используя "нормальные" объемы текста, а не миллиарды символов!), Я считаю, что для данных вершин простой, простой старый буфер вершин оправданно достаточно хорош считаться частью "современного решения". Это просто и понятно, это работает, и это работает хорошо.

Уже ссылаясь на " OpenGL Insights " выше, стоит также отметить главу "2D-рендеринг фигур по полям расстояний" Стефана Густавсона, в которой подробно объясняется рендеринг поля расстояний.

Обновление 2016:

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

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

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

И, наконец, хранение фактических кривых Безье, составляющие символы, а также оценки их в пиксельный шейдер стало практичным, с немного уступает производительность (но не так много, что это проблема) и потрясающие результаты даже при высоких увеличениях.
Демо-версия WebGL для рендеринга большого PDF с этой техникой в режиме реального времени доступна здесь.

Ответ 2

http://code.google.com/p/glyphy/

Основное отличие GLyphy от других OpenFL-рендерингов, основанных на SDF, заключается в том, что большинство других проектов объединяют SDF в текстуру. У этого есть все обычные проблемы, которые имеет выборка. То есть. он искажает контур и является низким качеством. GLyphy вместо этого представляет SDF, используя фактические векторы, представленные на GPU. Это приводит к очень качественному рендерингу.

Недостатком является то, что код для iOS с OpenGL ES. Я, вероятно, собираюсь сделать порт OpenGL 4.x для Windows/Linux (надеюсь, автор добавит некоторые реальные документы).

Ответ 3

Самый распространенный метод - это текстурированные квадрациклы. Однако в 2005 году LORIA разработала нечто, называемое векторными текстурами, то есть рендеринг векторной графики как текстуры на примитивах. Если вы используете это для преобразования шрифтов TrueType или OpenType в векторную текстуру, вы получаете следующее:

http://alice.loria.fr/index.php/[email protected]

Ответ 4

Я удивлен, что ребенок Майка Килгарда, NV_path_rendering (NVpr), не упоминался ни одним из вышеперечисленных. Хотя его цели более общие, чем рендеринг шрифтов, он также может отображать текст из шрифтов и кернинга. Он даже не требует OpenGL 4.1, но на данный момент это расширение для поставщика /Nvidia. Он в основном превращает шрифты в пути, используя glPathGlyphsNV, который зависит от библиотеки freetype2, чтобы получить метрики и т.д. Затем вы также можете получить доступ к информации о кернинге с помощью glGetPathSpacingNV и использовать механизм рендеринга общего пути NVpr для отображения текста с помощью метода path- "преобразованные" шрифты. (Я помещаю это в кавычки, потому что нет никакого реального преобразования, кривые используются как есть.)

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

В 2011 году презентация API NVpr API для части шрифтов начинается здесь и продолжается в следующая часть; немного неудачно, как разделение презентации.

Более общие материалы по NVpr:

  • Nvidia NVpr hub, но некоторые материалы на целевой странице не самые последние
  • документ Siggraph 2012 для мозгов метода рендеринга пути, называемый "трафарет, затем обложка" (StC); в документе также кратко объясняется, как работают конкурирующие технологии, такие как Direct2D. Биты, связанные с шрифтом, были отнесены к приложение к статье. Есть также некоторые дополнительные функции, такие как видео/демо.
  • презентация GTC 2014 для статуса обновления; вкратце: теперь он поддерживается Google Skia (Nvidia предоставил код в конце 2013 и 2014 годах), который, в свою очередь, используется в Google Chrome и [независимо от Skia, я думаю] в бета-версии Adobe Illustrator CC 2014
  • официальная документация в реестре расширений OpenGL
  • USPTO предоставил по крайней мере четыре патента на Kilgard/Nvidia в связи с NVpr, о которых вы, вероятно, должны знать, если вы хотите реализовать StC самостоятельно: US8698837, US8698808, US8704830 и US8730253. Обратите внимание, что к этому относится еще 17 документов USPTO, которые также "публикуются как", большинство из которых являются патентными заявками, поэтому от них могут быть предоставлены все больше патентов.

И поскольку слово "трафарет" не произвело никаких хитов на этой странице перед моим ответом, оно появляется подмножеством сообщества SO, которое участвовало на этой странице, хотя, несмотря на то, что оно довольно много, не знало о бесцветном трафарете, основанные на буфере методы для рендеринга путей/шрифтов в целом. У Kilgard есть часто задаваемый вопрос на форуме opengl, который может осветить то, как методы рендеринга пути без тесселяции отличаются от стандартной 3D-графики болота, хотя они все еще используют GPU [GP]. (NVpr нуждается в чипе CUDA.)

В исторической перспективе Килгард также является автором классического "Простой OpenGL-интерфейс для текстурированного текста" , SGI, 1997, которые не следует путать с основанной на трафарете NVpr, которая дебютировала в 2011 году.


В большинстве случаев, если не все последние методы, обсуждаемые на этой странице, в том числе основанные на трафарете методы, такие как методы NVpr или SDF, такие как GLyphy (которые я больше не обсуждаю здесь, потому что другие ответы уже охватывают его), однако одно ограничение: они подходят для отображения большого текста на обычных мониторах (~ 100 DPI) без зубьев на любом уровне масштабирования, а также они выглядят неплохо даже на небольших размерах на дисплеях с высоким разрешением DPI. Они не в полной мере предоставляют то, что Microsoft Direct2D + DirectWrite дает вам, а именно намек на небольшие глифы на основных дисплеях. (Для визуального обзора намеков вообще см. эта страница типотекнапример. Более подробный ресурс на antigrain.com.)

Я не знаю ни о каких открытых и продуктивных материалах на базе OpenGL, которые могут сделать то, что Microsoft может с намеком на данный момент. (Я признаю незнание Apple OS X GL/Quartz, потому что, насколько я знаю, Apple не опубликовала, как они делают материал для создания шрифтов/путей на основе GL. Кажется, что OS X, в отличие от MacOS 9, не вообще намекают, что раздражает некоторых людей.) В любом случае существует одна исследовательская работа в 2013 году, которая адреса, намекающие через шейдеры OpenGL, написанные INRIA Nicolas P. Rougier; это, вероятно, стоит прочитать, если вам нужно сделать намек на OpenGL. Хотя может показаться, что библиотека, такая как freetype, уже выполняет всю работу, когда дело доходит до намека, что на самом деле не так по следующей причине, которую я цитирую из статьи:

Библиотека FreeType может растрировать глиф, используя подпиксельное сглаживание в режиме RGB. Однако это только половина проблемы, так как мы также хотим достичь субпикселя позиционирование для точного размещения глифов. Отображение текстурированного квадратика в дробные координаты пикселей не решают проблему, так как это приводит только к текстуре интерполяция на уровне всего пикселя. Вместо этого мы хотим добиться точного сдвига (от 0 до 1) в субпиксельной области. Это можно сделать в шейдере фрагментов [...].

Решение не совсем тривиально, поэтому я не буду пытаться объяснить его здесь. (Документ открыт для доступа.)


Еще одна вещь, которую я узнал из бумаги Ружье (и которую Килгард, похоже, не рассмотрел) заключается в том, что полномочия шрифта, которые были (Microsoft + Adobe), создали не один, а два метода спецификации кернинга. Старый основан на так называемой таблице ядер и поддерживается freetype. Новый называется GPOS, и он поддерживается только новыми библиотеками шрифтов, такими как HarfBuzz или pango в мире свободного программного обеспечения. Поскольку NVpr, похоже, не поддерживает ни одну из этих библиотек, кернинг может не работать из коробки с NVpr для некоторых новых шрифтов; некоторые из них, по-видимому, находятся в дикой природе, согласно обсуждение этого форума.

Наконец, если вам нужно сделать сложный текстовый макет (CTL), вам кажется, что в настоящее время вам не повезло с OpenGL, поскольку OpenGL- основанная на существовании библиотеки. (DirectWrite, с другой стороны, может обрабатывать CTL.) Существуют библиотеки с открытым исходным кодом, такие как HarfBuzz, которые могут отображать CTL, но я не знаю, как вы могли бы заставить их работать хорошо (как при использовании методов, основанных на трафарете), через OpenGL. Вам, вероятно, придется написать код клея, чтобы извлечь переформатированные контуры и передать их в решения NVpr или SDF в качестве путей.

Ответ 5

Я думаю, что лучше всего было бы взглянуть на графику cairo с бэкэнд OpenGL.

Единственная проблема, с которой я столкнулся при разработке прототипа с 3,3 ядром, - это устаревшее использование функций в бэкэнде OpenGL. Это было 1-2 года назад, поэтому ситуация, возможно, улучшилась...

В любом случае, я надеюсь, что в будущем настольные графические драйверы opengl будут реализовывать OpenVG.