В OpenGL уже есть ряд вопросов о рендеринге текста, таких как:
Но в основном обсуждается рендеринг текстурированных квадов с использованием конвейера с фиксированной функцией. Конечно, шейдеры должны сделать лучше.
Я не очень обеспокоен интернационализацией, большинство моих строк будут помечены галочками (дата и время или чисто числовые). Но графики будут перерисованы с частотой обновления экрана, и там может быть довольно много текста (не более нескольких тысяч глифов на экране, но достаточно, чтобы компоновка с аппаратным ускорением была бы хорошей).
Каков рекомендуемый подход для рендеринга текста с использованием современного OpenGL? (Цитирование существующего программного обеспечения с использованием этого подхода является хорошим доказательством того, что оно работает хорошо)
- Геометрические шейдеры, которые принимают, например, положение и ориентацию и последовательность символов и испускают текстурированные квадраты
- Геометрические шейдеры, которые отображают векторные шрифты
- Как и выше, но вместо этого используются тесселяционные шейдеры
- Вычислительный шейдер для растеризации шрифтов
Ответы:
Рендеринг контуров, если только вы не отрисовываете всего дюжину символов, остается «не ходовым» из-за количества вершин, необходимых на символ для приблизительной кривизны. Хотя существуют подходы для оценки кривых Безье в пиксельном шейдере, они страдают от того, что их нелегко сглаживать, что тривиально при использовании квадрата с текстурированной картой расстояний, а вычисление кривых в шейдере все еще в вычислительном отношении намного дороже, чем необходимо.
Наилучшим компромиссом между «быстрым» и «качественным» по-прежнему являются текстурированные квадраты со текстурой поля со знаком. Это немного медленнее, чем при использовании обычного обычного текстурированного квадрата, но не так сильно. Качество, с другой стороны, совершенно другое. Результаты действительно потрясающие, они настолько быстрые, насколько вы можете получить, и такие эффекты, как свечение, тоже легко добавлять. Кроме того, методика может быть приятно понижена до более старого оборудования, если это необходимо.
Смотрите знаменитую бумагу Valve для техники.
Техника концептуально похожа на то, как работают неявные поверхности (метаболлы и т. Д.), Хотя она не генерирует многоугольники. Он полностью выполняется в пиксельном шейдере и принимает расстояние, выбранное из текстуры, как функцию расстояния. Все, что выше выбранного порога (обычно 0,5), находится «внутри», все остальное «вне». В простейшем случае на 10-летнем оборудовании, не поддерживающем шейдеры, установка порога альфа-теста на 0,5 будет делать именно это (но без специальных эффектов и сглаживания).
Если кто-то хочет добавить немного больше веса к шрифту (искусственно выделенный жирным шрифтом), немного меньший порог сделает свое дело без изменения одной строки кода (просто измените форму "font_weight"). Для эффекта свечения просто рассматривается все, что выше одного порога, как «внутри», а все, что выше другого (меньшего) порога, как «снаружи, но в сиянии», и LERP между ними. Сглаживание работает аналогично.
Используя 8-битное значение расстояния со знаком, а не один бит, этот метод увеличивает эффективное разрешение вашей карты текстуры в 16 раз в каждом измерении (вместо черного и белого используются все возможные оттенки, таким образом, мы имеем 256-кратное увеличение информация, использующая то же хранилище). Но даже если вы увеличите намного больше 16x, результат все равно выглядит вполне приемлемым. Длинные прямые линии со временем станут немного волнистыми, но типичных «блочных» артефактов сэмплирования не будет.
Вы можете использовать геометрический шейдер для генерации квадраторов из точек (уменьшить пропускную способность шины), но, честно говоря, выигрыши довольно незначительны. То же самое верно для рендеринга инстансированных символов, как описано в GPG8. Затраты на инстансинг амортизируются, только если у вас много текста для рисования. Преимущества, на мой взгляд, никак не связаны с дополнительной сложностью и возможностью снижения рейтинга. Кроме того, вы либо ограничены количеством константных регистров, либо должны считывать данные из объекта буфера текстур, что является неоптимальным для согласованности кэша (и целью было оптимизировать с самого начала!).
Простой, простой старый буфер вершин будет таким же быстрым (возможно, быстрее), если вы запланируете загрузку немного раньше времени, и будет работать на каждом оборудовании, созданном за последние 15 лет. И это не ограничивается каким-либо конкретным количеством символов в вашем шрифте, ни определенным количеством символов для визуализации.
Если вы уверены, что в вашем шрифте не более 256 символов, массивы текстур, возможно, стоит рассмотреть, чтобы обрезать полосу пропускания шины аналогично генерации четырехугольников из точек геометрического шейдера. При использовании текстуры массива координаты текстуры всех четырехугольников имеют одинаковую, постоянную
s
иt
координаты и отличаются толькоr
координатой, которая равна индексу символа для визуализации.Но, как и в случае с другими методами, ожидаемый выигрыш незначителен за счет несовместимости с оборудованием предыдущего поколения.
Есть удобный инструмент от Jonathan Dummer для генерации текстур на расстоянии: страница описания
Обновление:
как было недавно отмечено в Программируемом извлечении вершин (D. Rákos, «OpenGL Insights», стр. 239), нет никаких существенных дополнительных задержек или накладных расходов, связанных с программным извлечением данных вершин из шейдера на новейших поколениях графических процессоров, по сравнению с тем же, используя стандартную фиксированную функцию.
Кроме того, последние поколения графических процессоров имеют все больше и больше разумных размеров кэш-памяти L2 общего назначения (например, 1536 кБ на nvidia Kepler), поэтому можно ожидать, что проблема некогерентного доступа при вытягивании случайных смещений для четырехугольных углов из текстуры буфера будет меньше проблема.
Это делает идею извлечения постоянных данных (таких как размеры квадратов) из буферной текстуры более привлекательной. Таким образом, гипотетическая реализация может снизить до минимума передачи PCIe и памяти, а также памяти графического процессора при таком подходе:
gl_VertexID
, и усиливайте его до 4 точек в геометрическом шейдере, все еще имея индекс символа и идентификатор вершины (это будет "gl_primitiveID, сделанный доступным в вершинном шейдере") как единственные атрибуты, и получит это через обратную связь преобразования.Таким образом, в идеале можно уменьшить требуемую ширину полосы вершины на 75% (амортизироваться), хотя она сможет отображать только одну строку. Если бы кто-то хотел иметь возможность визуализировать несколько линий за один вызов отрисовки, ему нужно было бы добавить базовую линию к текстуре буфера, а не использовать униформу (уменьшая прирост пропускной способности).
Тем не менее, даже при условии 75% сокращения - поскольку данные вершин отображают «разумные» объемы текста, составляет всего лишь около 50-100 кБ (что практически равно нулю)к графическому процессору или шине PCIe) - я все еще сомневаюсь, что дополнительная сложность и потеря обратной совместимости действительно стоят того. Уменьшение нуля на 75% все еще только ноль. По общему признанию, я не пробовал вышеупомянутый подход, и необходимы дополнительные исследования, чтобы сделать действительно квалифицированное заявление. Но тем не менее, если кто-то не сможет продемонстрировать действительно ошеломляющую разницу в производительности (используя «нормальные» объемы текста, а не миллиарды символов!), Я считаю, что для данных вершин простой, простой старый буфер вершин вполне оправданно оправдан быть частью «современного решения». Это просто и понятно, это работает, и это работает хорошо.
Уже ссылаясь на « OpenGL Insights » выше, стоит также отметить главу «2D-рендеринг фигур по полям расстояний» Стефана Густавсона, в которой подробно объясняется рендеринг поля расстояний.
Обновление 2016:
Между тем, существует несколько дополнительных методов, которые направлены на удаление артефактов скругления углов, которые становятся мешающими при экстремальных увеличениях.
Один подход просто использует поля псевдодальности вместо полей расстояния (разница в том, что расстояние - это кратчайшее расстояние не до фактического контура, а до контура или воображаемой линии, выступающей над краем). Это несколько лучше и работает с той же скоростью (идентичный шейдер), используя тот же объем памяти текстур.
Другой подход использует медиану-три в трехканальных деталях текстуры и реализации, доступных на github . Это должно быть улучшение по сравнению с хакерами, которые использовались ранее для решения проблемы. Хорошее качество, немного, почти не заметно, медленнее, но использует в три раза больше памяти текстур. Кроме того, дополнительные эффекты (например, свечение) труднее получить право.
И, наконец, хранение фактических кривых Безье, составляющих символов, а также оценки их в пиксельный шейдер стал практичным , с немного уступает производительности (но не так много , что это проблема) и потрясающие результаты даже при высоких увеличениях.
Демо-версия WebGL для рендеринга большого PDF с этой техникой в режиме реального времени доступна здесь .
источник
clip(...)
строку наif (text.a < 0.5) {discard;}
(илиtext.a < threshold
). НТН.http://code.google.com/p/glyphy/
Недостатком является то, что код для iOS с OpenGL ES. Я, вероятно, собираюсь сделать порт для Windows / Linux OpenGL 4.x (надеюсь, автор добавит немного реальной документации).
источник
Самым распространенным методом по-прежнему остаются текстурированные четырехугольники. Однако в 2005 году LORIA разработала так называемые векторные текстуры, то есть рендеринг векторной графики в качестве текстур на примитивах. Если использовать это для преобразования шрифтов TrueType или OpenType в векторную текстуру, вы получите следующее:
http://alice.loria.fr/index.php/publications.html?Paper=VTM@2005
источник
Я удивлен, что ребенок Марка Килгарда , NV_path_rendering (NVpr), не был упомянут ни одним из вышеперечисленных. Хотя его цели являются более общими, чем рендеринг шрифтов, он также может отображать текст из шрифтов и с помощью кернинга. Он даже не требует OpenGL 4.1, но на данный момент это расширение только для поставщиков / Nvidia. Он в основном превращает шрифты в пути, используя
glPathGlyphsNV
которые зависит от библиотеки freetype2 для получения метрик и т. Д. Затем вы также можете получить доступ к информации оglGetPathSpacingNV
кернинге и использовать общий механизм рендеринга пути NVpr для отображения текста с использованием «преобразованных» шрифтов пути. (Я поместил это в кавычки, потому что нет реального преобразования, кривые используются как есть.)Записали демо для шрифта возможностей NVpr в это , к сожалению , не особенно впечатляет. (Может быть, кто-то должен сделать его в духе гораздо более захватывающей демонстрации SDF, которую можно найти в промежутках ...)
Доклад о презентации NVpr API 2011 для части шрифтов начинается здесь и продолжается в следующей части ; немного жаль, как эта презентация расколота.
Более общие материалы по NVpr:
И так как слово «трафарет» не произвело ни одного хита на этой странице до моего ответа, кажется, что подмножество SO-сообщества, которое участвовало на этой странице, поскольку, несмотря на то, что было довольно многочисленным, не знали о тесселяции, буфере буфера основанные методы для рендеринга пути / шрифта в целом. У Kilgard есть пост, похожий на FAQ, на форуме opengl, который может пролить свет на то, как методы рендеринга путей без тесселяции отличаются от стандартной трехмерной графики, даже если они все еще используют графический процессор [GP]. (NVpr нужен чип с поддержкой CUDA.)
С исторической точки зрения Килгард также является автором классического «Простого API на основе 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; Вероятно, стоит прочитать, если вам нужна подсказка от OpenGL. Хотя может показаться, что библиотека типа freetype уже выполняет всю работу, когда дело доходит до подсказок, на самом деле это не так по следующей причине, которую я цитирую из статьи:
Решение не совсем тривиально, поэтому я не буду пытаться объяснить это здесь. (Бумага открытого доступа.)
Еще одна вещь, которую я узнал из статьи Ружье (и которую Килгард, похоже, не учел), заключается в том, что возможности шрифтов (Microsoft + Adobe) создали не один, а два метода спецификации кернинга. Старый основан на так называемой таблице kern и поддерживается freetype. Новый называется GPOS и поддерживается только новыми библиотеками шрифтов, такими как HarfBuzz или pango в мире свободного программного обеспечения. Поскольку кажется, что NVpr не поддерживает ни одну из этих библиотек, кернинг может не работать из коробки с NVpr для некоторых новых шрифтов; Есть некоторые из тех, кто, по-видимому, в дикой природе, согласно этому обсуждению на форуме .
Наконец, если вам нужно сделать сложную разметку текста (CTL), вам кажется, что в настоящее время вам не повезло с OpenGL, так как для этого не существует библиотеки на основе OpenGL. (DirectWrite, с другой стороны, может обрабатывать CTL.) Существуют библиотеки с открытым исходным кодом, такие как HarfBuzz, которые могут визуализировать CTL, но я не знаю, как заставить их работать хорошо (как при использовании методов на основе трафарета) через OpenGL. Возможно, вам придется написать связующий код для извлечения измененных контуров и передачи их в решения на основе NVpr или SDF в качестве путей.
источник
Я думаю, что вам лучше всего рассмотреть каирскую графику с бэкэндом OpenGL.
Единственной проблемой, с которой я столкнулся при разработке прототипа с ядром 3.3, было устаревшее использование функций в бэкэнде OpenGL. Это было 1-2 года назад, так что ситуация могла бы улучшиться ...
В любом случае, я надеюсь, что в будущем настольные графические драйверы OpenGL будут реализовывать OpenVG.
источник