Рендеринг Текста Utf-8 С Использованием Шрифта Sdf

Продолжаем серию статей о разработке мобильных игр.

В этой статье я расскажу вам, как визуализировать текст UTF-8 с помощью растровых шрифтов SDF, как создавать эти шрифты и как использовать эту технику для качественного рендеринга иконок.



Рендеринг текста UTF-8 с использованием шрифта SDF



Содержание

Часть 1. Мобильный кроссплатформенный движок Часть 2. Отрисовка текста UTF-8 с использованием шрифта SDF. Часть 3. Рендеринг капли с прозрачностью и отражениями




Рендеринг текста UTF-8 с использованием шрифта SDF

СДФ ( Поле расстояния со знаком ) — изображение в оттенках серого, созданное на основе высококонтрастного черно-белого изображения, в котором уровень серого указывает расстояние до ближайшей границы контрастности.

Звучит запутанно, но на самом деле все очень просто.

Сам шрифт SDF выглядит так:

Рендеринг текста UTF-8 с использованием шрифта SDF

Давайте возьмем это изображение и изменим его уровни в Photoshop или любом другом графическом редакторе.



Рендеринг текста UTF-8 с использованием шрифта SDF

Уже выглядит лучше! У нас четкий шрифт со сглаживанием по краям.

Мы также можем выбрать смелый или тонкий стиль.

Но, к сожалению, вы не сможете получить курсив.

.



Рендеринг текста UTF-8 с использованием шрифта SDF

Главное преимущество SDF — возможность увеличивать шрифт без заметных артефактов.



Рендеринг текста UTF-8 с использованием шрифта SDF

Рекомендую прочитать больше о технологии SDF. здесь .

Как создать шрифт SDF? Прежде всего, вам нужно создать самый обычный черно-белый растровый шрифт. Вы можете сделать это старым добрым способом БМФонт или в УБФГ .

Для получения хороших результатов создайте шрифт размером 400 пикселей без сглаживания, с отступами 45x45x45x45 и размером изображения 4096x4096. Для таких размеров советую отключить Merging, т.к.

скорее всего UBGF зависнет. ?Экспортируем изображение в PNG без прозрачности, а формат описания желательно выбрать BMFont (для большей совместимости).



Рендеринг текста UTF-8 с использованием шрифта SDF

Далее нам понадобится ИзображениеМагия и следующая команда:

конвертировать шрифт.png -filter Jinc ( +clone -negate -morphology Расстояние Евклидово -уровень 50%, -50% ) -морфология Расстояние Евклидово -compose Plus -composite -level 43%,57% -resize 12,5%font.png
На выходе мы получим изображение размером 512х512, что в итоге даст нам очень хороший результат. Из файла описания нам нужно будет извлечь символы в Юникоде и их положение/размер (не забудьте разделить координаты на 8, так как мы уменьшили изображение).

Какие именно символы нужно экспортировать я расскажу ниже в разделе про UTF-8. Подождите, у UBFG есть встроенное поле расстояний! Да, у меня есть.

Но результат заметно хуже.

Возможно, авторы UBFG исправят это в обновлениях.

Шейдеры для рендеринга текста Вершинный шейдер чтобы напечатать каждую букву, символ за символом:

  
  
  
  
   

#ifdef DEFPRECISION precision mediump float; #endif attribute mediump vec2 Vertex; uniform highp mat4 MVP; uniform mediump vec2 cords[4]; varying mediump vec2 outTexCord; void main(){ outTexCord=Vertex*cords[3]+cords[2]; gl_Position = MVP * vec4(Vertex*cords[1]+cords[0], 0.0, 1.0); }

ДЕФПРЕЦИЗИЯ необходим для OpenGL ES. В шнуры[1] И шнуры[0] передаем положение и масштаб символа на экране.

И в шнуры[2] И шнуры[3] — координаты символа на текстуре шрифта.

Фрагментный шейдер

#ifdef DEFPRECISION precision mediump float; #endif varying mediump vec2 outTexCord; uniform lowp sampler2D tex0; uniform mediump vec4 color; uniform mediump vec2 params; void main(void){ float tx=texture2D(tex0, outTexCord).

r; float a=min((tx-params.x)*params.y, 1.0); gl_FragColor=vec4(color.rgb,a*color.a); }

В цвет передать цвет и прозрачность буквы.

И через параметры настроить толщину и сглаживание краев шрифта.

Если вы можете настроить толщину шрифта, то вы также сможете отобразить рамку! Шейдер фрагмента текста с рамкой :

#ifdef DEFPRECISION precision mediump float; #endif varying mediump vec2 outTexCord; uniform lowp sampler2D tex0; uniform mediump vec4 color; uniform mediump vec4 params; uniform mediump vec3 borderColor; void main(void){ float tx=texture2D(tex0, outTexCord).

r; float b=min((tx-params.z)*params.w, 1.0); float a=clamp((tx-params.x)*params.y, 0.0, 1.0); gl_FragColor=vec4(borderColor+(color.rgb-borderColor)*a, b*color.a); }

Дополнительно передаем толщину, сглаживая до params.zw и цвет рамки в цвет границы .

Результат должен выглядеть так:

Рендеринг текста UTF-8 с использованием шрифта SDF



Рендеринг текста UTF-8 с использованием шрифта SDF

Чтобы получить красивые края как для маленького, так и для большого размера текста, вам необходимо выбрать разные параметры контраста/сглаживания ( параметры ) для мелкого шрифта и для крупного шрифта.

Затем интерполируйте их до текущего размера.

По моему мнению, для небольшие размеры подходит хорошо:

  • более смелый стиль
  • более гладкие края
  • граница минимальна и размыта, чтобы не рябило
Для Большой размер :
  • более тонкий стиль шрифта
  • края очень острые
  • бордюр больше и острее
Иконки

Рендеринг текста UTF-8 с использованием шрифта SDF

Плоские иконки стали довольно популярными в современном дизайне.

Бесплатные векторные иконки полный полный .

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

Радиальный градиент придется делать попиксельно во фрагментном шейдере.

UTF-8 В современных проектах уже никто не использует однобайтовые кодировки.

Все перешли на UTF-8, wchar, unicode. Например, мне удобно работать со строками в кодировке UTF-8 char*.

UTF-8 легко декодируется в Юникод и идеально сочетается с Java/String и NSString. Функция преобразования UTF-8 в Unicode:

static inline unsigned int UTF2Unicode(const unsigned char *txt, unsigned int &i){ unsigned int a=txt[i++]; if((a&0x80)==0)return a; if((a&0xE0)==0xC0){ a=(a&0x1F)<<6; a|=txt[i++]&0x3F; }else if((a&0xF0)==0xE0){ a=(a&0xF)<<12; a|=(txt[i++]&0x3F)<<6; a|=txt[i++]&0x3F; }else if((a&0xF8)==0xF0){ a=(a&0x7)<<18; a|=(a&0x3F)<<12; a|=(txt[i++]&0x3F)<<6; a|=txt[i++]&0x3F; } return a; }

Бонус! Изменение реестра символов Юникода.



static inline unsigned int uppercase(unsigned int a){ if(a>=97 && a<=122)return a-32; if(a>=224 && a<=223)return a-32; if(a>=1072 && a<=1103)return a-32; if(a>=1104 && a<=1119)return a-80; if((a%2)!=0){ if(a>=256 && a<=424)return a-1; if(a>=433 && a<=445)return a-1; if(a>=452 && a<=476)return a-1; if(a>=478 && a<=495)return a-1; if(a>=504 && a<=569)return a-1; if(a>=1120 && a<=1279)return a-1; } return a; } static inline unsigned int lowercase(unsigned int a){ if(a>=65 && a<=90)return a+32; if(a>=192 && a<=223)return a+32; if(a>=1040 && a<=1071)return a+32; if(a>=1024 && a<=1039)return a+80; if((a%2)==0){ if(a>=256 && a<=424)return a+1; if(a>=433 && a<=445)return a+1; if(a>=452 && a<=476)return a+1; if(a>=478 && a<=495)return a+1; if(a>=504 && a<=569)return a+1; if(a>=1120 && a<=1279)return a+1; } return a; }



Блоки UTF-8

Большинство шрифтов, особенно креативных, содержат только ascii и латиницу.

Что делать, если нам нужны, например, символы валют? Особенно это актуально для платежей внутри приложений, где не доступны всевозможные валюты.

Предлагаю следующую схему, которая очень хорошо себя зарекомендовала:

Рендеринг текста UTF-8 с использованием шрифта SDF

Как узнать, какие символы есть в шрифте? Тут нам на помощь приходит странная штука от Adobe — тада! — пустой шрифт ! Его можно использовать в CSS: семейство шрифтов: Roboto, Adobe Blank; Именно так были получены пластины на картинке выше.

Останется только скопировать нужные куски символов и вставить их в UBFG. В результате мы получим несколько картинок размером 512х512, где каждая будет содержать столько символов, сколько в нее поместится.

Что это за универсальный шрифт? Шрифтов, содержащих большую часть символов Юникода, не так много.

я остановился на Кивира .

По крайней мере, с валютными символами у него все хорошо.



Рендеринг текста UTF-8 с использованием шрифта SDF

Допустим, вы добавили растровые изображения для арабского, японского и китайского языков.

Фоток будет очень много.

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

Еще есть загвоздка в том, что все шрифты имеют разные размеры и разные базовые линии.

При переключении со шрифта на шрифт текст будет прыгать.

Поэтому для каждого шрифта выберите параметры его относительного масштаба и смещения по оси Y. Учитывайте эти параметры при рендеринге каждого символа.



Рендеринг текста UTF-8 с использованием шрифта SDF

Я обещал булочки! Поймай это готово Шрифт SDF Quivira уже порезан на блоки! Теги: #шрифт #разработка мобильных устройств #iOS #Android #tvos #разработка iOS #C++ #Разработка мобильных приложений #Разработка игр #Разработка Android

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.