Контур шрифта в OpenGL, FTGL

8

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

(псевдокод)

font.render(Color::BLACK, position.x + 1, position.y + 1); // Shadow
font.render(Color::WHITE, position.x, position.y)          // Normal text

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

Рисовать контур просто крупным шрифтом - это неправильный путь, потому что, как я выяснил, буквы в этом случае просто не совпадают:

введите описание изображения здесь

Так есть ли простой способ создать схему для шрифтов? Как они это делают в реальных играх?

Заранее спасибо за любой ответ

Петр Хойнацкий
источник
1
Грязным решением может быть рендеринг в текстуру того же текста, а затем рендеринг этой текстуры, например, в масштабе х1.2.
Дэн,
2
@Dan Это приведет именно к тому, что он показал на своем изображении выше. Даже рендеринг по одной букве за раз таким образом может привести к проблемам, поскольку внешние контуры будут толще, чем внутренние (которые могут отсутствовать).
инженер
1
Какой тип шрифта вы используете? FTGL поддерживает Outline шрифты из коробки для векторных шрифтов. Ширина линии OpenGL может использоваться для контроля толщины.
Пол-Ян

Ответы:

7

Гибкость и точность: фильтры

Используйте фильтр texel либо на текстуре на стороне процессора, либо, если вы используете программируемый конвейер OpenGL, прямо в фрагментном шейдере.

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

Более быстрый способ сделать это - предварительно рассчитать набор смещений для каждого центрального пикселя, который вы проверяете; таким образом, вам не нужно запускать квадратный корень для каждого пикселя, окружающего данный пиксель. Другими словами, вы хотите уменьшить сложность до `O (texWidth * texHeight), а не O (texWidth * texHeight * filterRadius * filterRadius).

Легко: несколько рендеров

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

 \|/
--+--
 /|\

Смещая каждую из красных версий, как это, вы получите довольно однородный внешний край вокруг исходного текста. Имейте в виду, что при смещении по диагонали вы должны использовать ту же величину вектора, что и при смещении по горизонтали или вертикали, а не просто смещаться на те же значения x и y (что приводит к приблизительно в 1,4 раза большей длине - основной триггер).

FYI

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

инженер
источник
6

Эта функция реализована непосредственно в FTGL, но доступна только в ExtrudeFontклассе. Вы просто определяете начало для шрифта:

font = new FTExtrudeFont(...);
font->FaceSize(80);
font->Depth(0);
font->Outset(0, 5);

Затем вы можете использовать разные цвета для двух режимов рендеринга:

glColor3f(1.0, 1.0, 1.0); /* White inside */
font->Render("Hello", FTPoint(), FTPoint(), FTGL::RENDER_FRONT);
glColor3f(1.0, 0.0, 0.0); /* Red outline */
font->Render("Hello", FTPoint(), FTPoint(), FTGL::RENDER_SIDE);

Вот результат с включенным сглаживанием:

Результирующее изображение

Сэм Хоцевар
источник
Спасибо Сэм! Это действительно то, что я хотел услышать - у FTGL есть нечто подобное. Еще раз спасибо.
Петр Хойнацкий
2

Не имеет отношения к FTGL, но есть отличная статья от Valve о рендеринге глифов. Он обеспечивает высокое качество рендеринга с небольшими требованиями к памяти, и такие эффекты, как контуры или тени, могут быть просто реализованы.

Thelvyn
источник
2
Стоит предупредить OP, что этот подход требует понимания программируемого конвейера GPU, то есть шейдеров.
инженер