[JavaScript, Работа с 3D-графикой, WebGL] Рендеринг шрифтов для WebGL при помощи инстумента msdf-bmfont-xml и технологии MSDF

Автор Сообщение
news_bot ®

Стаж: 6 лет 2 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
21-Мар-2021 16:30

Пример: https://openglobus.org/examples/fonts/fonts.html18/3/2021 Наконец-то была закончена интеграция инструмента msdf-bmfont-xml для библиотеки openglobus. Текстовые метки стали выглядеть гораздо красивее! Мне помог инструмент msdf-bmfont-xml для создания атласов шрифтов и рендеринга текстур для (multichannel signed distance fields) MSDF.
Пример по ссылке: https://openglobus.org/examples/fonts/fonts.htmlmsdf-bmfont-xml предлагает широкие возможности для формирования текстурных атласов из шрифтов в формате ttf. В нашем случае, текстура атласа представляет из себя многоканальную карту расстояний (multichannel signed distance fields), которая позволяет отображать острые углы букв, в отличии от оригинального signed distance field.В этой статье я хочу расскать, что из себя представляет атлас для хранения букв, и как отображать текст при помощи WebGL. Текстурный атлас msdf-bmfont-xmlТекстурный атлас шрифта, это текстура с сохраненными на ней картинками символов. Каждая картинка имеет соответствующие текстурные координаты. 
Текстура 512x512 для атласа шрифта Roboto-RegularДля создания атласа я использую комманду:
msdf-bmfont.cmd - reuse -i .\charset.txt -m 512,512 -f json -o %1.png -s 32 -r 8 -p 1 -t msdf %1
где %1 — имя файла шрифта в формате ttf, charset.txt — это файл с набором символов для которых строится атлас, про остальные параметры можно узнать на официальной страничке репозитория msdf-bmfont-xml:При успешном выполненении команды создаются несколько файлов, нас будут интересовать текстура атласа в формате png и описание атласа в формате json.В полученном файле описания json информация по символам хранится в разделе chars. Например, символ ‘q’ на картинке атласа расположен в координатах x = 131, y = 356, width = 22, height = 32. т.е. координаты левого правого угола [131, 356] и правого нижнего соответственно [131+22, 356+32]. Таким образом, если размер текстуры атласа равен 512 на 512 пикселей, значит текстурные координат сомвола ‘q’ соответственно будут равны [131/512, 356/512 ] и [153/512, 388/512]. Если передать эти текстурные координаты в шейдер, который рисует прямоугольник, то мы увидем в этом прямоугольнике наш символ. Кроме того, у нас имеется ширина и высота символа, согласно этим данным мы устанавливаем размер прямоугольника, чтобы символ выглядел пропорционально правильным.
{
    id: 113,
    char: "q",
    width: 22,
    height: 32,
    xoffset: -3,
    yoffset: 11,
    xadvance: 18,
    x: 131,
    y: 356,
    ...
}
Другими важными параметрами для позиционирования символа являются:xoffsеt — Смещение символа по горизонталиyoffset — Смещение символа по вертикалиxadvance — Ширина символа; расстояние от левой границы символа до начала следующего символа в строке.А также id символа по которому можно идентифицировать символ в таблице горизонтальных кернингов. Кернинг — это расстояние между двумя специфическими символами.Пример: изображения строки “Wg!” шрифт ArialПарметры символов:
W: width: 37, height: 31, xoffset: -4, yoffset: 4, xadvance: 30
g: width: 23, height: 32, xoffset: -3, yoffset: 10, xadvance: 18
! : width: 11, height: 31, xoffset: -1, yoffset: 4, xadvance: 9
Центром координат является левый верний угол, изначально символы располагаются на одной прямой относительно верхней зеленой линии по вертикали и относительно левой зеленой линии по горизонтали, и имеют смещение относительно друг друга согласно параметрам width.
Следующая картинка показывает смещение символов относительно горизонтальной (центральной) оси по вертикали, параметр yoffsset.
Голубыми линиями обозначен параметр xadvance (расстояние до следующего символа), также каждый символ смещен по горизонтали согласно параметру xoffset.
Текущий вариант можно считать готовым, однако для лучшего качества следует применить параметры для кернинга, т.е. смещение относительно друг друга двух специфических символов. В этом примере я не показываю кернинги; кернинг учитывается в параметре xoffset во время отображения текста.Рендеринг текста MSDFОтрисовка массива вершин символа производится методом gl.drawArrays, где исходным буффером является буффер массива вершин для атрибута a_vertices:
vec2 a_vertices = [0, 0, 0, -1, 1, -1, 1, -1, 1, 0, 0, 0]
Основные параметры символов предварительно нормализуются при построении атласа шрифта:
imageSize = 512; //размер текстуры атласа
nWidth = width / imageSize; //нормализованная ширина символа
nHeight = height / imageSize; //нормализованная высота глифа
nAdvance = xadvance / imageSize; //нормализованный размер глифа до следующего символа в строке
nXOffset = xoffset / imageSize; //нормализованное смещение по горизонтали
nYOffset = 1.0 - yoffset / imageSize; //нормализованное смещение по вертикали
Шейдер GLSLИсходник: https://github.com/openglobus/openglobus/blob/master/src/og/shaders/label.js
// Vertex shader:
// ...
vec2 v = screenPos + (a_vertices * a_gliphParam.xy + a_gliphParam.zw + vec2(advanceOffset, 0.0)) * a_size;
// Где:
// screenPos - экранные координаты строки
// a_vertices - Координаты вершин
// a_gliphParam - вектор с метриками символа, где:
// x - nWidth, y - nHeight, z - nXOffset, w - nYOffset
// advanceOffset - сумарное смещение по параметру nAdvance, каждого последующего сомвола в строке
// a_size - экранные размеры строки в пикселях
// Fragment shader:
// ...
const float imageSize = 512.0;
const float distanceRange = 8.0;
layout(location = 0) out vec4 outScreen;
float median(float r, float g, float b) {
    return max(min(r, g), min(max(r, g), b));
}
float getDistance() {
    vec3 msdf = texture(fontTexture, v_uv).rgb;
    return median(msdf.r, msdf.g, msdf.b);
}
void main () {
    vec2 dxdy = fwidth(v_uv) * vec2(imageSize);
    float dist = getDistance() + min(v_weight, 0.5 – 1.0 / DIST_RANGE) - 0.5;
    float opacity = clamp(dist * distanceRange / length(dxdy) + 0.5, 0.0, 1.0);
    outScreen = vec4(v_rgba.rgb, opacity * v_rgba.a);
}
// Где:
// fontTexture - текстура атласа шрифтов
// v_weight - ширина символа от 0 до 1, используется для окантовки, по умолчанию равен 0.
// Окантовка рисуется ПЕРВЫМ проходом с заданным v_weight.
// v_uv - текстурные координаты символа в атласе шрифтов
// v_rgba - цвет символа, или окантовки
// ...
Надеюсь, что я достаточно понятно объяснил, как работать с атласами шрифтов и как я использую msdf-bmfont-xml для своего проекта. Этот подход существенно улучшил качество текстовых меток на карте.
Пример редактора планировщика маршрута БПЛА компании Microavia c использованием библиотеки OpenglobusПишите в комментариях, чем вы пользуетесь, для рендеринга шрифтов, и как на ваш взгляд можно улучшить качество текстовых меток?Если у вас возникнут вопросы по применению моей рекомендации можете задать их на openglobusфоруме https://groups.google.com/forum/#!forum/openglobus, и я обязательно отвечу!Желаю Вам хорошего настроения!Полезные источники
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_javascript, #_rabota_s_3dgrafikoj (Работа с 3D-графикой), #_webgl, #_webgl, #_openglobus, #_sdf, #_msdf, #_3d, #_javascript, #_javascript, #_rabota_s_3dgrafikoj (
Работа с 3D-графикой
)
, #_webgl
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 27-Апр 20:10
Часовой пояс: UTC + 5