Рендеринг текста в WebVR

В деталях

Посмотреть сайт

Within ( https://with.in/ ) — это платформа для рассказывания историй в виртуальной реальности. Поэтому, когда команда услышала о WebVR в 2015 году, мы сразу заинтересовались его потенциалом. Сегодня этот интерес проявляется в уникальном поддомене нашей веб-платформы https://vr.with.in/ . Любой, у кого есть браузер с поддержкой VR, может зайти на сайт, нажать кнопку и надеть гарнитуру, чтобы погрузиться в наше портфолио VR-фильмов.

Сегодня это включает, помимо прочего, Chrome в Daydream View. Информацию о вашем устройстве и головном дисплее можно найти на https://webvr.info/ .

Как и другие среды рендеринга, специфичные для виртуальной реальности, Интернет преимущественно полагается на трехмерное представление сцены. В этой сцене есть камера, ваша перспектива и любое количество объектов. Чтобы управлять этой сценой, камерой и объектами, мы используем библиотеку Three.js , которая использует элемент <canvas> для передачи рендеринга на графический процессор вашего компьютера. Существует множество полезных дополнений Three.js, которые сделают вашу сцену доступной для просмотра в WebVR. Два основных — это THREE.VREffect для создания окна просмотра для каждого глаза и THREE.VRControls для убедительной трансляции перспективы (например, вращения и положения головного дисплея) в вашу сцену. Есть много примеров того, как это реализовать. Ознакомьтесь с примерами Three.js WebVR , чтобы узнать, как начать работу.

По мере дальнейшего изучения WebVR мы столкнулись с проблемой. Если мы посмотрим на содержимое Интернета, текст станет его неотъемлемой частью. Хотя большая часть нашего контента основана на видео, если вы зайдете на сайт Within, контент будет окружен текстом; Пользовательский интерфейс и дополнительная информация о фильме или связанных с ним фильмах состоят из текста. Более того, весь этот текст создается в DOM. Наши исследования WebVR и https://vr.with.in/ находятся в <canvas> .

Текст, используемый в WebVRТекст, используемый в WebVR
Текст, используемый в WebVR для vr.with.in

Какие у меня есть варианты?

К счастью, работа над тем, чтобы это стало возможным, ведется. Фактически, в ходе нашего исследования мы нашли ряд эффективных способов визуализации текста в трехмерной среде с помощью элемента <canvas> . Ниже приведена таблица из нескольких найденных нами, отмеченных плюсами и минусами для каждого:

Независимый от разрешения Типографские особенности Производительность Простота реализации
2D-текст на холсте Да Да Да
Триангулированный векторный текст Да Да
Выдавленный 3D-текст Да
Текст растрового изображения поля расстояния со знаком Да Да Да

Наше решение: растровый шрифт SDF

2D-холст с ctx.fillText() может выполнять перенос текста, интервал между буквами и высоту строки, но переполнение обрезается, и текст будет размытым, если вы очень сильно увеличите масштаб. Вы можете увеличить размер текстуры холста, но это может привести к превышению верхнего предела размера текстуры или производительности, если текстура окажется слишком большой.

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

Рабочий процесс преобразования шрифта в растровое изображение SDF
Рабочий процесс преобразования шрифта в растровое изображение SDF

В растровых шрифтах на каждый символ используется один квадрат (два треугольника), поэтому они используют меньше геометрии и работают лучше, чем триангулированные векторы . Они по-прежнему основаны на растре, поскольку используют спрайт карты текстуры, но с шейдером SDF они в основном не зависят от разрешения, поэтому выглядят лучше, чем текстура 2D-холста. Three-bmfont-text Мэтта ДеЛорье также включает в себя надежные типографские функции для переноса текста, межбуквенного интервала, высоты строки и выравнивания. Перелив не отсекается. Размер шрифта контролируется посредством масштаба. Мы выбрали этот путь, потому что он дает нам лучшие варианты дизайна, сохраняя при этом производительность. К сожалению, реализовать это оказалось не так просто, поэтому мы пройдемся по шагам в надежде помочь коллегам-разработчикам, работающим в WebVR.

1. Создайте растровый шрифт (.png + .fnt).

Интерфейс Иеро
Интерфейс Иеро
Вывод Hiero (растровый PNG и файл .fnt)Вывод Hiero (растровый PNG и файл .fnt)
Вывод Hiero (растровый PNG и файл .fnt)

Hiero — это инструмент для упаковки растровых шрифтов, работающий с Java. Документация Hiero действительно не объясняет, как ее запустить, не проходя сложный процесс сборки. Сначала установите Java, если вы еще этого не сделали. Затем, если дважды щелкните на runnable hiero.jar не открывает Hiero, попробуйте запустить его с этой командой в консоли:

java -jar runnable-hiero.jar

После запуска Hiero откройте настольный шрифт .ttf или .otf, введите любые дополнительные символы, которые вы хотите включить, измените рендеринг на Java, чтобы включить эффекты, увеличьте размер, чтобы ваши символы заполняли весь квадрат кэша глифов, добавьте поле расстояния. Эффект, отрегулируйте масштаб и разбросайте поля расстояния. Значение масштаба аналогично разрешению. Чем выше это, тем меньше он будет размытым, но чем дольше будет понадобиться Иеро, чтобы представить предварительный просмотр. Затем сохраните растровый шрифт. Он генерирует растровый шрифт, состоящий из изображения .png и файла AngelCode .fnt Font.

2. Преобразование AngelCode в JSON

Теперь, когда был сгенерирован шрифт растрового изображения, мы должны загрузить его в наше приложение JavaScript с пакетом Matt Deslauriers 'Load-Bmfont NPM .

Мы могли бы браузеризировать load-bmfont и использовать его во внешнем интерфейсе, но вместо этого мы собираемся запустить load-bmfont.js с Node, чтобы преобразовать и сохранить AngelCode .fnt Hiero в файл .json :

npm install
node load-bmfont.js
Пример вывода JSON
Пример вывода JSON

Теперь мы можем обойти Load-Bmfont и просто выполнить запрос XHR (xmlhttprequest) в файле шрифта .json.

var r = new XMLHttpRequest();
r.open('GET', 'fonts/roboto/bitmap/roboto-bold.json');

r.onreadystatechange = function() {
    if (r.readyState === 4 && r.status === 200) {
    setup(JSON.parse(r.responseText));
    }
};

r.send();

function setup(font) {
    // pass font into TextBitmap object
}

3. Просмотрите три-bmfont-text

После того, как мы загрузили шрифт, три-BMFONT-текст Мэтта позаботится об остальном. Поскольку мы не используем Node для нашего собственного приложения, мы собираемся браузелифицировать Three-bmfont-Text.js в полезную трех bmfont-text-bundle.js

npm install -g browserify
browserify three-bmfont-text.js -o three-bmfont-text-bundle.js

4. SDF-шейдер

Отрегулируйте AFWIDTH и пороговые ползунки на vr.with.in/archive/text-sdf-bitmap/ , чтобы увидеть влияние подписанного шейдера поля расстояния.

5. Использование

Для удобства я создал класс-оболочку TextBitmap для браузерного текста Three-bmfont-text.

Text-sdf-bitmap в действии
Text-sdf-bitmap в действии
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

Создайте запрос XHR для файла шрифта .json и создайте текстовый объект в обратном вызове:

var bmtext = new TextBitmap({ options });

Чтобы изменить текст:

bmtext.text = 'The quick brown fox jumps over the lazy dog.';

scene.add( bmtext.group );
hitBoxes.push( bmtext.hitBox );

Pitmap шрифт.

TextBitmap также включает в себя невидимый хитбокс для взаимодействия с помощью Raycast Three.js через мышь, камеру или контроллеры движения с ручным отслеживанием, такие как Oculus Touch или контроллеры Vive. Автоматическое обновление Hitbox при изменении параметров текста.

Bmtext.group добавляется в сцену Three.js. Если вам нужен доступ к дочерним элементам/Object3D, граф сцены для текста выглядит так:

Схема файловой системы

6. Уменьшите json и измените xoffsets.

В текстовом формате gif

Если кернинг не работает, возможно, вам придется отредактировать смещения x в файле json. Вставьте JSON в jsbeautifier.org , чтобы получить неизменную версию файла.

Xoffset — это, по сути, глобальный кернинг для одного символа. Кернинг предназначен для двух конкретных символов, которые появляются рядом друг с другом. Значения по умолчанию в массиве кернинга на самом деле не имеют значения, и редактировать их было бы слишком утомительно, поэтому вы можете очистить этот массив, чтобы уменьшить размер файла json. Затем отредактируйте смещения x для кернинга.

Сначала вам нужно выяснить, какие символы соответствуют идентификатору символа в json. В Three-bmfont-text-bundle.js вставьте console.log после строки 240:

    var id = text.charCodeAt(i)
    // console.log(id);

Затем введите текстовое поле dat.gui на https://vr.with.in/archive/text-sdf-bitmap/ и проверьте консоль, чтобы найти соответствующий идентификатор персонажа.

Например, в нашем шрифте растрового изображения «J» неизменно слишком далеко вправо. Его идентификатор символа — 106. Итак, найдите "id": 106 в json и измените его xoffset с -1 на -10.

7. Планировка

Если у вас есть несколько блоков текста и вы хотите, чтобы он перемещался сверху вниз, как HTML, все необходимо позиционировать вручную, аналогично абсолютному позиционированию каждого элемента dom самостоятельно с помощью CSS. Можете ли вы представить себе, как это можно сделать с помощью CSS?

    * { position: absolute; }

Вот что такое макет текста в 3D. В подробном представлении: заголовок, автор, описание и продолжительность - это новый объект Textbitmap со своими собственными стилями, цветом, масштабами и т. Д.:

3d макет
author.group.position.y = title.group.position.y - title.height - padding;
description.group.position.y = author.group.position.y - author.height - padding;
duration.group.position.y = description.group.position.y - description.height - padding;

При этом предполагается, что локальное начало каждой группы TextBitmap вертикально выровнено с верхом сетки TextBitmap (см. центрирование в обновлении text-bitmap.js ). Если вы измените текст для любого из этих объектов позже, и высота этого объекта изменится, вам также необходимо будет пересчитать эти позиции. Здесь изменяется только положение текста по оси Y, но одна из возможностей работы в 3D заключается в том, что мы можем толкать и тянуть текст в направлении z, а также вращать вокруг осей x, y и z.

Заключение

Текст и макет в WebVR предстоит пройти долгий путь, прежде чем они столь же просты и широко используются, как HTML и CSS. Но работающие решения существуют, и вы можете сделать гораздо больше с помощью WebVR, чем с традиционной веб-страницей HTML. WebVR существует сегодня. Вероятно, завтра появятся инструменты получше. А пока пробуйте и экспериментируйте. Разработка без универсальной структуры приводит к созданию более уникальных проектов, и это интересно.