Renderowanie tekstu w WebVR

W szczegółach

Wyświetlanie witryny

W obrębie (https://with.in/) to platforma do marketingu narracyjnego w rzeczywistości wirtualnej. Gdy w 2015 r. zespół usłyszał o WebVR, od razu zainteresowało się jego potencjałem. Dziś to zainteresowanie przejawia się w unikalnej subdomenie naszej platformy internetowej https://vr.with.in/. Każdy, kto ma przeglądarkę z włączoną obsługą VR, może wejść na stronę, kliknąć przycisk i założyć gogle, by zanurzyć się w naszej kolekcji filmów VR.

Obecnie dotyczy to m.in. Chrome w Daydream View. Informacje o urządzeniu i wyświetlaczu zakładanym na głowę znajdziesz na stronie https://webvr.info/.

Podobnie jak w przypadku innych środowisk renderowania specyficznych dla rzeczywistości wirtualnej, sieć opiera się głównie na trójwymiarowej reprezentacji sceny. Do tej sceny składa się kamera, perspektywa i dowolna liczba obiektów. Aby ułatwić zarządzanie tą sceną, kamerą i obiektami, używamy biblioteki o nazwie Three.js, która korzysta z elementu <canvas> do wysyłania renderowania na GPU komputera. Jest wiele przydatnych dodatków Three.js, które umożliwiają wyświetlanie sceny w WebVR. Główne 2 to THREE.VREffect służą do tworzenia widocznego obszaru dla każdego oka oraz THREE.VRControls do przenoszenia perspektywy (np.obrót i położenia wyświetlacza zamontowanego na głowie) w przekonujący sposób. Jest wiele przykładów, jak to zrobić. Zacznij od zapoznania się z przykładami WebVR w Three.js.

W miarę głębszego poznawania technologii WebVR natrafiliśmy na problem. W przypadku treści internetowych tekst jest ich integralną częścią. Choć większość naszych materiałów bazuje na filmach, to jeśli otworzysz tekst W witrynie, interfejs i dodatkowe informacje o filmie lub powiązanych filmach są wyświetlane w formie tekstowej. Ponadto cały tekst jest tworzony w modelu DOM. Nasze eksploracje WebVR i https://vr.with.in/ są dostępne w <canvas>.

Tekst używany w WebVR Tekst używany w WebVR
Tekst używany w WebVR na potrzeby vr.with.in

Jakie mam opcje?

Na szczęście robimy wszystko, aby to było możliwe. W naszych badaniach znaleźliśmy wiele skutecznych sposobów renderowania tekstu w trójwymiarowym środowisku za pomocą elementu <canvas>. Poniżej znajdziesz ich zestawienie z wadami i zaletami każdej z nich:

Niezależne od rozdzielczości Właściwości typograficzne Występy Łatwość wdrożenia
Tekst obszaru roboczego 2D Tak Tak Tak
Tekst wektorowy elitarny Tak Tak
Wycięty tekst 3D Tak
Podpisany tekst mapy bitowej pola odległości Tak Tak Tak

Nasza decyzja: czcionka mapy bitowej plików SDF

Obszar roboczy 2D z atrybutem ctx.fillText() umożliwia zawijanie tekstu, odstępy między literami i wysokość wierszy, ale przepełnienie jest przycinane, a duże powiększenie tekstu może być rozmyte. Możesz zwiększyć rozmiar tekstury odbitki na płótnie, ale jeśli jest ona zbyt duża, może zostać osiągnięty górny limit rozmiaru tekstury lub może to obniżyć wydajność.

Wyciśnięty tekst 3D jest zasadniczo taki sam jak trójkątny tekst wektorowy, ale z głębią i możliwym ścięciem, dzięki czemu ma co najmniej dwa razy większą geometrię. Każde z tych formatów może sprawdzić się w małych dawkach w przypadku tytułów lub logo, ale nie sprawdza się w przypadku dużych ilości tekstu i żadna z nich nie ma cech typograficznych.

Przepływ pracy z czcionką do pliku mapy bitowej SDF
Przepływ pracy związany z przepływem pracy z czcionki do bitmapy SDF

Czcionki bitmapy używają 1 czworokąta (2 trójkątów) na znak, więc mają mniej geometrii i działają lepiej niż wektory trójkątne. W dalszym ciągu są to obiekty rastrowe, ponieważ używają sprite'ów z mapą tekstur. W przypadku cieniowania SDF są w zasadzie niezależne od rozdzielczości, więc wyglądają ładniej niż w przypadku tekstur płótno 2D. Tekst 3-bmfont-text Matta DesLauriersa zawiera też niezawodne funkcje typograficzne służące do zawijania tekstu, odstępów między literami, wysokości wiersza i wyrównywania. Wielkość czcionki nie zostaje przycięta. Rozmiar czcionki zależy od skali. Wybraliśmy tę trasę, bo daje nam ona najlepsze opcje projektowania przy jednoczesnym zachowaniu wydajności. Wdrożenie nie było tak proste, dlatego przejdziemy przez kolejne kroki, mając nadzieję, że uda nam się pomóc innym programistom pracującym w WebVR.

1. Wygeneruj czcionkę mapy bitowej (.png + .fnt)

Interfejs Hiero
Interfejs Hiero
Dane wyjściowe Hiero (pliki Bitmap PNG i .fnt) Dane wyjściowe Hiero (pliki Bitmap PNG i .fnt)
Dane wyjściowe Hiero (pliki Bitmap PNG i .fnt)

Hiero to narzędzie do pakowania czcionek bitmapowych, które działa w Javie. W dokumentacji Hiero nie wyjaśniamy, jak ją uruchomić bez przeprowadzenia skomplikowanego procesu kompilacji. Najpierw zainstaluj Javę. Jeśli następnie dwukrotne kliknięcie pliku runnable-hiero.jar nie spowoduje otwarcia Hiero, spróbuj uruchomić go w konsoli za pomocą tego polecenia:

java -jar runnable-hiero.jar

Po uruchomieniu Hiero otwórz czcionkę na komputery w formacie .ttf lub .otf, wpisz dodatkowe znaki, zmień renderowanie na Java, by włączyć efekty, zwiększ rozmiar tak, by znaki wypełniały cały kwadrat pamięci podręcznej glifów, dodaj efekt pola odległości, dostosuj skalę pola odległości i rozłóż. Wartość skali jest jak rozdzielczość. Im wyższa jest ta wartość, tym mniej jest rozmyte, ale im dłużej trwa renderowanie podglądu przez Hiero. Zapisz czcionkę mapy bitowej. Generuje bitmapę z obrazem w formacie .png i plikiem z opisem czcionek AngelCode.

2. Konwertuj AngelCode na JSON

Czcionka bitmapy została wygenerowana, więc musimy wczytać ją do naszej aplikacji w języku JavaScript za pomocą pakietu npm Matta DesLauriersa.

Mogliśmy skorzystać z przeglądarki load-bmfont i wykorzystać ją w interfejsie, ale zamiast tego uruchomimy load-bmfont.js z węzłem, aby przekonwertować plik AngelCode .fnt Hiero i zapisać go w pliku.json:

npm install
node load-bmfont.js
Przykład wyjściowego pliku JSON
Przykład wyjściowego formatu JSON

Teraz możemy ominąć parametr load-bmfont i wysłać żądanie XHR (XMLHttpRequest) w pliku czcionek .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. Browserify w postaci tekstu 3-bmfont

Gdy czcionka jest już załadowana, tekst Matta w formacie 3-bmfont zajmie się całą resztą. Ponieważ w naszej aplikacji nie używamy węzła, wstawimy plik browserify three-bmfont-text.js w użyteczny plik three-bmfont-text-bundle.js

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

4. Program do cieniowania SDF

Dostosuj suwaki afwidth i threshold na vr.with.in/archive/text-sdf-bitmap/, aby zobaczyć wpływ cieniowania podpisanego pola odległości.

5. Wykorzystanie

Dla ułatwienia utworzyliśmy klasę opakowania TextBitmap dla tekstu 3 bmfont w przeglądarce.

Text-sdf-bitmap w działaniu
Text-sdf-bitmap w działaniu
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

Utwórz żądanie XHR dla pliku czcionek .json i utwórz obiekt tekstowy w wywołaniu zwrotnym:

var bmtext = new TextBitmap({ options });

Aby zmienić tekst:

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

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

Plik .png czcionki bitmapy został wczytany za pomocą polecenia THREE.TextureLoader w pliku text-bitmap.js.

TextBitmap zawiera też niewidoczne pole hitu do interakcji raycast z 3.js za pomocą myszy, kamery lub ręcznie śledzonych kontrolerów ruchu, takich jak Oculus Touch czy Vive. Rozmiar okna działania jest aktualizowany automatycznie, gdy zmienisz opcje tekstu.

Element Bmtext.group został dodany do scenythree.js. Jeśli chcesz uzyskać dostęp do obiektów podrzędnych lub Object3D, wykres sceny dla tekstu wygląda tak:

Diagram systemu plików

6. Zminimalizowanie pliku JSON i modyfikowanie xoffsets

GIF w tekście

Jeśli kerning nie działa, konieczne może być zmodyfikowanie xoffset w pliku JSON. Wklej kod JSON do Jsbeautifier.org, aby uzyskać jego ujednoliconą wersję.

xoffset to zasadniczo globalny kerning dla jednego znaku. Kerning jest przeznaczony dla dwóch specjalnych znaków, które pojawiają się obok siebie. Domyślne wartości w tablicy kerningu w rzeczywistości nie mają znaczenia, a edytowanie tej tablicy byłoby zbyt pracochłonne, dlatego można opróżnić tę tablicę, aby zmniejszyć rozmiar pliku JSON. Następnie edytuj wartości xoffset na potrzeby kerningu.

Najpierw musisz ustalić, które znaki występują w poszczególnych identyfikatorach znaków w pliku JSON. W pliku three-bmfont-text-bundle.js po wierszu 240 wstaw console.log:

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

Następnie wpisz go w polu tekstowym dat.gui na stronie https://vr.with.in/archive/text-sdf-bitmap/ i sprawdź w konsoli odpowiedni identyfikator znaku.

Na przykład w naszej czcionce bitmapowej „j” jest stale za daleko po prawej. Identyfikator znaku to 106. Znajdź więc "id": 106 w pliku json i zmień jego wartość xoffset z -1 na -10.

7. Układ

Jeśli masz wiele bloków tekstu i chcesz, by unosił się on z góry na dół tak jak w kodzie HTML, wszystko musisz ustawić ręcznie, podobnie jak w kodzie CSS bezwzględnego pozycjonowania każdego elementu dom. Czy wyobrażasz sobie, jak możesz to zrobić w CSS?

    * { position: absolute; }

Tak właśnie wygląda układ tekstu w 3D. W widoku szczegółów: tytuł, autor, opis i czas trwania to nowe obiekty TextBitmap z własnymi stylami, kolorem, skalą itp.:

Układ 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;

Zakładamy tutaj, że lokalne źródło każdej grupy TextBitmap jest wyrównane pionowo do górnej części siatki TextBitmap (patrz wyśrodkowanie w aktualizacji text-bitmap.js). Jeśli później zmienisz tekst dowolnego z tych obiektów, a jego wysokość się zmieni, trzeba będzie ponownie obliczyć te pozycje. W tym przypadku zmienia się tylko pozycja tekstu na osi Z, ale jedna z możliwości pracy w 3D polega na tym, że możemy przesuwać i wyciągać tekst w kierunku Z oraz obracać go wokół osi x, y i z.

Podsumowanie

Zanim tekst i układ będzie tak łatwy w użyciu jak HTML i CSS, wiele się da w systemie WebVR. Istnieją jednak działające rozwiązania. W WebVR można zrobić o wiele więcej niż w przypadku tradycyjnej strony HTML. WebVR jest już dostępne. Jutro prawdopodobnie dostępne będą lepsze narzędzia. Do tego czasu możesz ją wypróbować i poeksperymentować. Tworzenie projektów bez uniwersalnej struktury sprawia, że powstaje więcej unikalnych projektów.