Простое решение C ++ для создания текстур растровых шрифтов для OpenGL, DirectX или Vulkan

Растровые шрифты - это распространенный способ визуализации текста в компьютерных графических API, таких как OpenGL, DirectX или Vulkan. Растровый шрифт - это большая текстура со всеми символами ASCII (или более) на ней. Затем текст может быть визуализирован путем создания четырехугольника для каждой буквы с применением к нему правильной части текстуры растрового шрифта.

Как создать текстуру растрового шрифта?

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

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

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

Создайте растровый шрифт с помощью FreeType

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

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

Инициализировать FreeType

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

Теперь мы можем выделить немного памяти для нашего растрового изображения. Поскольку имеется 128 символов ASCII (хотя первые 32 не печатаются), нам нужно изображение со 128 фрагментами и разделить его на 8 строк по 16 столбцов в каждой. Мы также добавляем 2 пикселя заполнения к нашему размеру шрифта, чтобы не было растекания текстуры при плохом масштабировании результирующей текстуры.

Показатели персонажа

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

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

Рисование персонажей

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

Теперь все сложное позади, и нам просто нужно сохранить растровое изображение в файл. Вот код для этого, или просто посмотрите полный код внизу руководства.

использование

Использовать генератор растровых шрифтов очень просто. Просто дайте ему файл шрифта и желаемый размер, а также имена файлов для ваших выходных данных (в Windows вы можете найти фактические файлы шрифтов ваших установленных шрифтов в C:/Windows/Fonts/).

Ширина символов

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

Примечания

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

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

Ресурсы

Вам нравится такой контент? Получите неограниченный доступ ко всем историям и поддержите меня и других писателей, присоединившись к Medium. Если вы зарегистрируетесь по этой ссылке, часть вашего членского взноса пойдет мне.