Rzeczywistość rozszerzona: być może już to wiesz

Jeśli zdarzyło Ci się już korzystać z interfejsu WebXR Device API, prawdopodobnie udało Ci się go osiągnąć.

Joe Medley
Joe Medley

Interfejs WebXR Device API został wysłany jesienią zeszłego roku w Chrome 79. Jak już wspomnieliśmy, trwa wdrażanie tego interfejsu API w Chrome. Chrome z przyjemnością informuje, że niektóre prace zostały zakończone. W Chrome 81 pojawiły się 2 nowe funkcje:

Ten artykuł dotyczy rzeczywistości rozszerzonej. Jeśli już korzystałeś(-aś) z interfejsu WebXR Device API, ucieszy Cię informacja, że nie trzeba jeszcze uczyć się obsługi. Rozpoczęcie sesji WebXR w dużym stopniu odbywa się tak samo. Zapętlanie ramki przebiega w zasadzie tak samo. Różnice wynikają z konfiguracji, które umożliwiają odpowiednie wyświetlanie treści w rzeczywistości rozszerzonej. Jeśli nie znasz podstawowych pojęć związanych z WebXR, przeczytaj moje wcześniejsze posty o interfejsie WebXR Device API lub przynajmniej zapoznaj się z poruszanymi w nim tematami. Potrafisz poprosić o sesję i dołączyć do niej oraz wiedzieć, jak uruchomić pętlę ramek.

Informacje o testowaniu trafień znajdziesz w artykule towarzyszącym Pozycjonowanie obiektów wirtualnych w widokach rzeczywistych. Kod w tym artykule jest oparty na przykładowej sesji Immersive AR Session (prezentacja źródło) z przykładów interfejsu WebXR Device API od Immersive Web Working Group.

Zanim zagłębimy się w kod, skorzystaj z przykładowej sesji Immersive AR co najmniej raz. Potrzebujesz nowoczesnego telefonu z Androidem i Chrome 81 lub nowszą wersją.

Do czego służy?

Rzeczywistość rozszerzona będzie cennym dodatkiem do wielu istniejących i nowych stron internetowych, ponieważ umożliwi implementowanie przypadków użycia AR bez opuszczania przeglądarki. Na przykład może pomóc użytkownikom w nauce w witrynach edukacyjnych i umożliwić potencjalnym nabywcom wizualizację przedmiotów w ich domu podczas zakupów.

Rozważmy drugi przypadek użycia. Wyobraź sobie, że symulujesz w rzeczywistej scenie rzeczywistą wielkość obiektu wirtualnego. Po umiejscowieniu obraz pozostaje na wybranej powierzchni i ma taki rozmiar, jaki miałby być, gdyby znajdował się na niej dany element. Umożliwia to użytkownikowi przesuwanie się wokół niej, a także bliższe jej obrócenie. Dzięki temu widzowie mogą lepiej zrozumieć dany obiekt, niż w przypadku obrazów dwuwymiarowych.

Wyprzedzam się trochę. Aby wykonać to, co opisałem, potrzebujesz funkcji AR i pewnych sposobów wykrywania platform. Artykuł dotyczy poprzedniego. W tym artykule znajdziesz informacje o tym drugim artykule na temat interfejsu WebXR Hit Test API (link do strony powyżej).

Wysyłanie prośby o sesję

Żądanie sesji jest bardzo podobne do tego, którego widziałeś(-aś) wcześniej. Najpierw sprawdź, czy wybrany typ sesji jest dostępny na bieżącym urządzeniu, dzwoniąc pod numer xr.isSessionSupported(). Zamiast wysyłać żądanie 'immersive-vr', poproś o to 'immersive-ar'.

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

Tak jak poprzednio, włączenie tej opcji powoduje włączenie przycisku „Enter AR” (Wpisz AR). Gdy użytkownik go kliknie, wywołaj xr.requestSession(), a także przekaże 'immersive-ar'.

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

Nieruchomość udogodnień

W ostatnim przykładowym kodzie zostały wyróżnione 2 wiersze. Wygląda na to, że obiekt XRSession ma właściwość o nazwie isImmersive. To udoskonalona przeze mnie właściwość, która nie jest częścią specyfikacji. Wykorzystam ją później do podjęcia decyzji o tym, co pokazać widzom. Dlaczego ta właściwość nie jest częścią interfejsu API? Aplikacja może śledzić tę właściwość w inny sposób, więc autorzy specyfikacji zdecydowali się utrzymać porządek w interfejsie API.

Rozpoczęcie sesji

Przypomnij sobie, jak wyglądał tekst onSessionStarted() we wcześniejszym artykule:

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

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

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

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

Muszę dodać kilka rzeczy, aby uwzględnić renderowanie rzeczywistości rozszerzonej. Wyłącz tło. Najpierw muszę określić, czy potrzebuję tła. Od tego miejsca będę korzystać z mojej usługi dogodnej.

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

  if (session.isImmersive) {
    removeBackground();
  }

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

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

  refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
  xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
    xrSession.requestAnimationFrame(onXRFrame);
  });

}

Obszary referencyjne

Moje wcześniejsze artykuły przeglądały miejsca referencyjne. W próbce, którą opisuję, wykorzystam 2 z nich, więc pora to poprawić.

Przestrzeń referencyjna opisuje relację między światem wirtualnym a środowiskiem fizycznym użytkownika. Jest to możliwe dzięki:

  • Określanie punktu początkowego układu współrzędnych używanego do wyrażania pozycji w świecie wirtualnym.
  • Określa, czy użytkownik ma poruszać się w obrębie tego układu współrzędnych.
  • Określa, czy ten układ współrzędnych ma wcześniej ustalone granice. (Te przykłady nie dotyczą układów współrzędnych z ustalonymi wcześniej granicami).

We wszystkich przestrzeniach referencyjnych współrzędna X oznacza lewo i prawo, Y – w górę i w dół, a Z – do przodu i do tyłu. Wartości dodatnie to odpowiednio pionowo, w górę i w tył.

Współrzędne zwracane przez funkcję XRFrame.getViewerPose() zależą od żądanego typu przestrzeni referencyjnej. Więcej o tym dowiesz się, gdy dojdziemy do pętli klatek. Na razie musimy wybrać typ pliku referencyjnego odpowiedni dla rzeczywistości rozszerzonej. Ponownie korzystamy z mojej dogodnej usługi.

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

  if (session.isImmersive) {
    removeBackground();
  }

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

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

  refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
  xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

Po przejściu do przykładowej sesji AR zauważysz, że początkowo scena jest nieruchoma, a rzeczywista rozszerzona w ogóle nie jest. Aby poruszać się po scenie, możesz przeciągać i przesuwać palcem. Po kliknięciu „ROZPOCZNIJ AR” tło zniknie i będzie można poruszać się po scenie, poruszając urządzeniem. Tryby korzystają z różnych typów przestrzeni referencyjnej. Zaznaczony tekst powyżej pokazuje, jak jest wybierany. Używa tych typów odwołań:

local – źródło znajduje się w miejscu przeglądającego w momencie tworzenia sesji. Oznacza to, że doświadczenie nie musi mieć jasno określonej ceny, a dokładne położenie może się różnić w zależności od platformy. Choć nie ma wstępnie ustalonych granic, to treści można oglądać bez żadnych ruchów poza obracaniem. Jak widać na naszym przykładzie AR, można się poruszać w obrębie przestrzeni.

viewer – najczęściej używane w przypadku treści prezentowanych w treści strony, w tym miejscu umiejscowionym po ekranie urządzenia. Przekazana do getViewerPose nie zapewnia śledzenia, więc zawsze zgłasza pozę w źródle, chyba że aplikacja zmieni ją za pomocą funkcji XRReferenceSpace.getOffsetReferenceSpace(). W przykładzie jest to możliwe, aby umożliwić przesuwanie dotykowe kamery.

Zapętlanie klatek

Ogólnie rzecz biorąc, nic się nie zmienia od tego, co robiłem w sesji VR opisanej w moich wcześniejszych artykułach. Przekaż typ pokoju referencyjnego do funkcji XRFrame.getViewerPose(). Zwrócony XRViewerPose będzie dotyczył bieżącego typu przestrzeni referencyjnej. Jeśli ustawisz wartość viewer jako domyślną, strona będzie wyświetlać podgląd treści, zanim użytkownik poprosi użytkownika o zgodę na korzystanie z rzeczywistości rozszerzonej lub wirtualnej. Świadczy to o ważnej kwestii: treść wbudowana wykorzystuje tę samą pętlę klatek co treść przewijana, co zmniejsza ilość kodu do utrzymania.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  let xrViewerPose = xrFrame.getViewerPose(refSpaceType);
  if (xrViewerPose) {
    // Render based on the pose.
  }
}

Podsumowanie

Ta seria artykułów zawiera tylko podstawowe informacje o implementowaniu treści interaktywnych w internecie. Znacznie więcej możliwości i przypadków użycia znajdziesz w przykładach korzystania z WebXR Device API organizacji Immersive Web zmniejszająca zasięg. Właśnie opublikowaliśmy artykuł z testu trafień, w którym wyjaśniamy, jak działa interfejs API służący do wykrywania powierzchni i umieszczania wirtualnych przedmiotów w widoku rzeczywistym z kamery. Możesz je przeglądać i oglądać na blogu web.dev, w którym w kolejnym roku znajdziesz kolejne artykuły.

Zdjęcie: David Grandmougin, Unsplash