Rzeczywistość wirtualna w internecie

kilka podstawowych informacji, które przygotują Cię na spektrum wciągających doznań: rzeczywistości wirtualnej, rzeczywistości rozszerzonej i wszystkiego pomiędzy.

Joe Medley
Joe Medley

W Chrome 79 pojawiły się wciągające treści. Interfejs WebXR Device API umożliwia korzystanie z rzeczywistości wirtualnej, a w Chrome 81 pojawiła się obsługa rzeczywistości rozszerzonej. Zaktualizowany interfejs GamePad API umożliwia zaawansowane sterowanie w VR. Wkrótce inne przeglądarki będą obsługiwać te specyfikacje, w tym Firefox Reality, Oculus Browser, Edge i przeglądarka Helio firmy Magic Leap.

Z tego artykułu rozpoczyna się seria poświęcona rzeczywistości rozszerzonej. Ta rata obejmuje konfigurowanie podstawowej aplikacji WebXR oraz rozpoczynanie i zamykanie sesji XR. W kolejnych artykułach omówimy pętlę ramki (główny element interfejsu WebXR), specyfikę rzeczywistości rozszerzonej oraz interfejs WebXR Hit Test API, który służy do wykrywania powierzchni w sesji AR. O ile nie zaznaczono inaczej, wszystko, o czym piszę w tym i kolejnych artykułach, dotyczy zarówno AR, jak i VR.

Czym jest immersyjna sieć?

Chociaż używamy 2 terminów na określenie doświadczenia immersyjnego – rzeczywistość rozszerzona i rzeczywistość wirtualna – wiele osób traktuje je jako spektrum rzeczywistości – od rzeczywistości pełnej po wirtualny, z stopniowym zanurzeniem się między sobą. Litera „X” w XR ma odzwierciedlać to podejście, ponieważ jest rodzajem zmiennej algebraicznej, która oznacza wszystko w zakresie doświadczeń w środowisku.

Wykres ilustrujący spektrum doświadczeń wizualnych od pełnej rzeczywistości do pełnego wrażenia.
Zakres wciągających doświadczeń

Przykłady wciągających doświadczeń:

  • Gry
  • Filmy 360°
  • tradycyjne filmy 2D (lub 3D) prezentowane w realistycznym otoczeniu;
  • Zakup domu
  • Wyświetlanie produktów w domu przed zakupem
  • Wciągająca sztuka
  • Coś fajnego, o czym nikt jeszcze nie pomyślał

Pojęcia i wykorzystanie

Wyjaśnię kilka podstawowych kwestii związanych z korzystaniem z interfejsu WebXR Device API. Jeśli potrzebujesz więcej informacji, zajrzyj do próbek WebXR grupy roboczej Immersive Web lub do stale rosnącej liczby materiałów referencyjnych MND. Jeśli znasz wczesną wersję interfejsu WebXR Device API, przeczytaj ją w całości. Wprowadzono zmiany.

Kod w tym artykule jest oparty na minimalnym przykładzie grupy roboczej Immersive Web (demo, źródło), ale został zmodyfikowany w celu zwiększenia przejrzystości i prostoty.

W ramach tworzenia specyfikacji WebXR opracowano środki bezpieczeństwa i prywatności, które chronią użytkowników. W związku z tym implementacje muszą spełniać określone wymagania. Strona internetowa lub aplikacja musi być aktywna i zaznaczona, aby mogła żądać od użytkownika jakichkolwiek poufnych informacji. Strony internetowe lub aplikacje muszą być wyświetlane przez HTTPS. Interfejs API został zaprojektowany tak, aby chronić informacje uzyskane z czujników i kamer, których potrzebuje do działania.

Prośba o sesję

Rozpoczęcie sesji XR wymaga gestu użytkownika. Aby to zrobić, użyj wykrywania cech w celu przetestowania funkcji XRSystem (za pomocą navigator.xr) i wywołaj polecenie XRSystem.isSessionSupported(). Pamiętaj, że w Chrome w wersjach 79 i 80 obiekt XRSystem miał nazwę XR.

W przykładzie poniżej wskazałem, że chcę utworzyć sesję rzeczywistości wirtualnej z typem sesji 'immersive-vr'. Pozostałe typy sesji to 'immersive-ar' i 'inline'. Sesja wstawiona służy do prezentowania treści w kodzie HTML i jest używana głównie w przypadku treści teaserowych. Przykład zajęcia z użyciem rozszerzonej rzeczywistości to potwierdza. Omówię to w następnym artykule.

Gdy wiem, że sesje rzeczywistości wirtualnej są obsługiwane, włączam przycisk, który pozwala mi uzyskać gest użytkownika.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter VR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

Po włączeniu przycisku czekam na zdarzenie kliknięcia, a potem proszę o sesję.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-vr')
    .then((session) => {
      xrSession = session;
      xrButton.textContent = 'Exit XR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

Zwróć uwagę na hierarchię obiektów w tym kodzie. Przechodzi z navigator do xr do wystąpienia XRSession. W wcześniejszych wersjach interfejsu API skrypt musiał poprosić o urządzenie, zanim poprosił o sesję. Teraz urządzenie jest nabywane bezpośrednio.

Dołączanie do sesji

Po otrzymaniu sesji muszę ją rozpocząć i wejść do niej. Najpierw jednak muszę skonfigurować kilka rzeczy. Sesja wymaga modułu obsługi zdarzenia onend, aby można było zresetować aplikację lub stronę internetową po wyjściu użytkownika.

Do rysowania sceny potrzebuję też elementu <canvas>. Musi to być kontekst WebGLRenderingContext lub WebGL2RenderingContext zgodny z XR. Wszystkie rysunki są tworzone za pomocą tych obiektów lub za pomocą frameworka opartego na WebGL, takiego jak Three.js.

Teraz, gdy mam miejsce do rysowania, potrzebuję źródła treści, na których będę rysować. W tym celu tworzę instancję XRWebGLLayer. Powiązanie go z płótnem odbywa się przez wywołanie funkcji XRSession.updateRenderState().

Podczas sesji potrzebuję sposobu, aby określić, gdzie jest rzeczywistość. Potrzebuję miejsca na odniesienie. 'local-floor'przestrzeń odniesienia to przestrzeń, w której początek układu współrzędnych znajduje się w pobliżu widza, a oś Y ma wartość 0 na poziomie podłogi i nie powinna się przesuwać. Istnieją inne typy przestrzeni referencyjnych, ale to bardziej skomplikowany temat, niż mógłbym tutaj omówić. Przechowuję przestrzeń referencyjną w zmiennej, ponieważ będę jej potrzebować, gdy będę rysować na ekranie.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

Po uzyskaniu przestrzeni odniesienia wywołuję funkcję XRSession.requestAnimationFrame(). Jest to początek prezentacji treści wirtualnych, która odbywa się w pętli klatki.

Uruchamianie pętli ramek

Ramka pętli to nieskończona pętla kontrolowana przez użytkownika, w której treści są wielokrotnie wyświetlane na ekranie. Zawartość jest rysowana w postaci dyskretnych bloków nazywanych ramkami. Kolejność klatek tworzy iluzję ruchu. W przypadku aplikacji VR liczba klatek na sekundę może wynosić od 60 do 144. AR na Androidzie działa z prędkością 30 klatek na sekundę. Kod nie powinien zakładać konkretnej liczby klatek.

Podstawowy proces pętli ramki:

  1. Zadzwoń do firmy XRSession.requestAnimationFrame(). W odpowiedzi na to klient użytkownika wywołuje zdefiniowaną przez Ciebie funkcję XRFrameRequestCallback.
  2. W obrębie funkcji wywołania zwrotnego:
    1. Zadzwoń ponownie do XRSession.requestAnimationFrame().
    2. Uchwyć się w pozycji widza.
    3. Przekazywanie (bindowanie) WebGLFramebufferXRWebGLLayer do WebGLRenderingContext.
    4. Przetwarzaj każdy obiekt XRView, pobierając z niego element XRViewport z obiektu XRWebGLLayer i przekazując go do elementu WebGLRenderingContext.
    5. Narysuj coś na framebufferze.

Pozostała część tego artykułu opisuje krok 1 i część kroku 2, czyli konfigurowanie i wywoływanie funkcji XRFrameRequestCallback. Pozostałe elementy kroku 2 są omawiane w części II.

Zwracanie wywołania zwrotnego XRFrameRequestCallback

Pole XRFrameRequestCallback jest definiowane przez Ciebie. Przyjmuje 2 parametry: instancję DOMHighResTimeStampXRFrame. Obiekt XRFrame zawiera informacje potrzebne do renderowania pojedynczego klatki na wyświetlaczu. Argument DOMHighResTimeStamp jest przeznaczony do użycia w przyszłości.

Zanim zrobię cokolwiek innego, poproszę o kolejną klatkę animacji. Jak już wspomnieliśmy, czas wyświetlania klatek jest określany przez klienta użytkownika na podstawie sprzętu. Żądanie następnej klatki jako pierwszej zapewnia, że pętla klatki będzie kontynuowana, jeśli podczas wywołania zwrotnego wystąpi błąd.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  // Render a frame.
}

W tym momencie nadszedł czas, aby narysować coś dla widza. To temat na część II. Zanim to zrobimy, pokażę Ci, jak zakończyć sesję.

Zakończ sesję

Sesja wrażeń może zostać zakończona z różnych powodów, m.in. przez Twój kod wywołujący funkcję XRSession.end(). Inne przyczyny to odłączenie zestawu słuchawkowego lub przejęcie nad nim kontroli przez inną aplikację. Dlatego aplikacja o dobrym zachowaniu powinna monitorować zdarzenie end. Gdy tak się stanie, odrzuć sesję i powiązane z nią obiekty renderowania. Zakończonej sesji w trybie immersyjnym nie można wznowić. Aby ponownie wejść do trybu pełnoekranowego, aplikacja musi rozpocząć nową sesję.

Pamiętasz z Wchodzenie do sesji, że podczas konfiguracji dodałem element obsługi zdarzenia onend.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);
  // More setup…
}

W module obsługi zdarzeń przywróć stan aplikacji, zanim użytkownik rozpoczął sesję.

function onSessionEnded(event) {
  xrSession = null;
  xrButton.textContent = 'Enter VR';
}

Podsumowanie

Nie omówiliśmy wszystkich kwestii związanych z tworzeniem aplikacji XR lub AR w internecie. Mam nadzieję, że udało mi się przekazać Ci wystarczająco dużo informacji, abyś mógł/mogła zacząć samodzielnie analizować kod i przeprowadzać eksperymenty. W następnym artykule omówię pętlę klatek, czyli miejsce, w którym treść jest wyświetlana na ekranie.

Zdjęcie: JESHOOTS.COM, Unsplash