1. Zanim zaczniesz
W tym ćwiczeniu w Codelabs znajdziesz przykład tworzenia aplikacji internetowej AR. Do renderowania modeli 3D, które wyglądają, jakby istniały w rzeczywistym świecie, używa się JavaScriptu.
Korzystasz z interfejsu WebXR Device API, który łączy funkcje rzeczywistości rozszerzonej i wirtualnej (VR). Skupisz się na rozszerzeniach AR interfejsu WebXR Device API, aby utworzyć prostą aplikację AR działającą w interaktywnej sieci.

Co to jest AR?
AR to termin zwykle używany do opisywania mieszania grafiki generowanej komputerowo ze światem rzeczywistym. W przypadku AR na telefonie oznacza to przekonujące nakładanie grafiki komputerowej na przekaz z kamery na żywo. Aby ten efekt pozostał realistyczny podczas przemieszczania się telefonu, urządzenie z AR musi rozpoznawać otoczenie i określać swoją pozycję (położenie i orientację) w przestrzeni 3D. Może to obejmować wykrywanie powierzchni i szacowanie oświetlenia otoczenia.
Po wprowadzeniu przez Google ARCore i przez Apple ARKit rozszerzona rzeczywistość stała się powszechnie stosowana w aplikacjach, np. w filtrach do selfie czy grach opartych na AR.
Co utworzysz
W tym ćwiczeniu w Codelabs utworzysz aplikację internetową, która umieszcza model w rzeczywistym świecie za pomocą rzeczywistości rozszerzonej. Twoja aplikacja będzie:
- Używanie czujników urządzenia docelowego do określania i śledzenia jego pozycji i orientacji w świecie
- Renderowanie modelu 3D nałożonego na obraz z kamery na żywo
- Przeprowadzanie testów trafień w celu umieszczania obiektów na wykrytych powierzchniach w prawdziwym świecie
Czego się nauczysz
- Jak korzystać z WebXR Device API
- Jak skonfigurować podstawową scenę AR
- Jak znaleźć powierzchnię za pomocą testów trafień AR
- Jak wczytać i wyrenderować model 3D zsynchronizowany z przekazem z kamery w świecie rzeczywistym
- Renderowanie cieni na podstawie modelu 3D
Te ćwiczenia z programowania dotyczą interfejsów AR API. Nieistotne koncepcje i bloki kodu zostały zamaskowane. Można je znaleźć w odpowiednim kodzie repozytorium.
Czego potrzebujesz
- Stacja robocza do kodowania i hostowania statycznych treści internetowych
- Urządzenie z Androidem obsługujące ARCore z Androidem 8.0 (Oreo).
- Google Chrome
- zainstalowane Usługi Google Play dla AR (Chrome automatycznie wyświetla prośbę o ich zainstalowanie na zgodnych urządzeniach);
- wybranym przez Ciebie serwerze WWW.
- kabel USB do podłączenia urządzenia AR do stacji roboczej;
- Przykładowy kod
- edytor tekstu,
- Podstawowa znajomość HTML, CSS, JavaScriptu i Narzędzi deweloperskich w Chrome
Kliknij Wypróbuj na urządzeniu AR, aby wypróbować pierwszy krok tego samouczka. Jeśli pojawi się strona z komunikatem „Twoja przeglądarka nie ma funkcji AR”, sprawdź, czy na urządzeniu z Androidem są zainstalowane Usługi Google Play dla AR.
2. Konfigurowanie środowiska programistycznego
Pobieranie kodu
- Kliknij ten link, aby pobrać na stację roboczą cały kod do tego laboratorium:
- Rozpakuj pobrany plik ZIP. Spowoduje to rozpakowanie folderu głównego (
ar-with-webxr-master), który zawiera katalogi z kilkoma etapami tego samouczka oraz wszystkie potrzebne zasoby.
Foldery step-03 i step-04 zawierają oczekiwany stan końcowy trzeciego i czwartego kroku tego ćwiczenia oraz wynik final. Są one podane w celach informacyjnych.
Całą pracę związaną z kodowaniem wykonujesz w katalogu work.
Instalowanie serwera WWW
- Możesz używać własnego serwera WWW. Jeśli nie masz jeszcze skonfigurowanego serwera, w tej sekcji znajdziesz szczegółowe informacje o konfigurowaniu serwera Web Server for Chrome.
Jeśli nie masz jeszcze tej aplikacji zainstalowanej na stacji roboczej, możesz ją zainstalować z Chrome Web Store.
- Po zainstalowaniu aplikacji Web Server for Chrome otwórz
chrome://appsi kliknij ikonę serwera WWW:
![]()
Następnie zobaczysz to okno dialogowe, w którym możesz skonfigurować lokalny serwer WWW:

- Kliknij wybierz folder i wybierz folder
ar-with-webxr-master. Dzięki temu możesz wyświetlać swoje prace w trakcie tworzenia za pomocą adresu URL wyróżnionego w oknie serwera internetowego (w sekcji Adresy URL serwera internetowego). - W sekcji Opcje (wymaga ponownego uruchomienia) zaznacz pole wyboru Automatycznie wyświetlaj plik index.html.
- Przełącz Serwer WWW na Zatrzymaj, a potem z powrotem na Uruchomiono.

- Sprawdź, czy wyświetla się co najmniej 1 adres URL serwera internetowego: http://127.0.0.1:8887 – domyślny adres URL hosta lokalnego.
Skonfiguruj przekierowanie portów
Skonfiguruj urządzenie AR tak, aby po otwarciu na nim adresu localhost:8887 uzyskiwał dostęp do tego samego portu na stacji roboczej.
- Na stacji roboczej programisty otwórz chrome://inspect i kliknij Przekazywanie portów...:

- W oknie Ustawienia przekierowania portów przekieruj port 8887 na localhost:8887.
- Zaznacz pole wyboru Włącz przekierowanie portów:

Sprawdzanie konfiguracji
Sprawdź połączenie:
- Podłącz urządzenie AR do stacji roboczej za pomocą kabla USB.
- Na urządzeniu AR w Chrome wpisz http://localhost:8887 na pasku adresu. Urządzenie AR powinno przekazać to żądanie do serwera WWW stacji roboczej dewelopera. Powinien pojawić się katalog plików.
- Na urządzeniu AR kliknij
step-03, aby załadować plikstep-03/index.htmlw przeglądarce.
Powinna się wyświetlić strona z przyciskiem Włącz rzeczywistość rozszerzoną. | Jeśli jednak zobaczysz stronę błędu Nieobsługiwana przeglądarka, Twoje urządzenie prawdopodobnie nie jest zgodne. |
|
|
Połączenie z serwerem WWW powinno teraz działać na urządzeniu AR.
- Kliknij Rozpocznij rzeczywistość rozszerzoną. Może pojawić się prośba o zainstalowanie ARCore.

Gdy po raz pierwszy uruchomisz aplikację AR, zobaczysz prośbę o przyznanie uprawnień do korzystania z aparatu.
→ 
Gdy wszystko będzie gotowe, zobaczysz scenę z kostkami nałożoną na przekaz z kamery. Rozpoznawanie sceny poprawia się w miarę analizowania przez aparat większej części świata, więc poruszanie się może pomóc w ustabilizowaniu obrazu.

3. Konfigurowanie WebXR
W tym kroku dowiesz się, jak skonfigurować sesję WebXR i podstawową scenę AR. Strona HTML jest dostarczana ze stylami CSS i kodem JavaScript, który umożliwia korzystanie z podstawowych funkcji AR. Usprawnia to proces konfiguracji, dzięki czemu można skupić się na funkcjach AR.
strona HTML,
Do tworzenia środowiska AR na tradycyjnej stronie internetowej używasz istniejących technologii internetowych. W tym przypadku używasz obszaru renderowania na pełnym ekranie, więc plik HTML nie musi być zbyt złożony.
Funkcje AR wymagają gestu użytkownika, aby je uruchomić, dlatego istnieją komponenty Material Design do wyświetlania przycisku Uruchom AR i komunikatu o nieobsługiwanej przeglądarce.
Plik index.html, który znajduje się już w katalogu work, powinien wyglądać mniej więcej tak: Jest to podzbiór rzeczywistej zawartości. Nie kopiuj tego kodu do pliku.
<!-- Don't copy this code into your file! -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building an augmented reality application with the WebXR Device API</title>
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<!-- three.js -->
<script src="https://unpkg.com/three@0.123.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.123.0/examples/js/loaders/GLTFLoader.js"></script>
<script src="../shared/utils.js"></script>
<script src="app.js"></script>
</head>
<body>
<!-- Information about AR removed for brevity. -->
<!-- Starting an immersive WebXR session requires user interaction. Start the WebXR experience with a simple button. -->
<a onclick="activateXR()" class="mdc-button mdc-button--raised mdc-button--accent">
Start augmented reality
</a>
</body>
</html>
Otwórz kluczowy kod JavaScript
Punkt początkowy aplikacji znajduje się w regionie app.js. Ten plik zawiera kod początkowy do skonfigurowania środowiska AR.
Katalog roboczy zawiera już kod aplikacji (app.js).
Sprawdzanie obsługi WebXR i AR
Zanim użytkownik zacznie korzystać z AR, sprawdź, czy istnieje navigator.xr i czy są dostępne niezbędne funkcje XR. Obiekt navigator.xr jest punktem wejścia interfejsu WebXR Device API, więc powinien istnieć, jeśli urządzenie jest zgodne. Sprawdź też, czy obsługiwany jest tryb sesji "immersive-ar".
Jeśli wszystko jest w porządku, kliknięcie przycisku Wejdź w rzeczywistość rozszerzoną spowoduje próbę utworzenia sesji XR. W przeciwnym razie wywoływana jest funkcja onNoXRDevice() (w shared/utils.js), która wyświetla komunikat o braku obsługi AR.
Ten kod jest już obecny w app.js, więc nie trzeba wprowadzać żadnych zmian.
(async function() {
if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) {
document.getElementById("enter-ar").addEventListener("click", activateXR)
} else {
onNoXRDevice();
}
})();
Poproś o XRSession
Gdy klikniesz Enter augmented Reality (Wejdź w rzeczywistość rozszerzoną), kod wywoła funkcję activateXR(). Spowoduje to uruchomienie AR.
- Znajdź funkcję
activateXR()w plikuapp.js. Pominięto część kodu:
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = /* TODO */;
// Omitted for brevity
}
Punktem wejścia do WebXR jest XRSystem.requestSession(). Użyj trybu immersive-ar, aby wyświetlać wyrenderowane treści w środowisku rzeczywistym.
- Zainicjuj
this.xrSessionw trybie"immersive-ar":
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = await navigator.xr.requestSession("immersive-ar");
// ...
}
Zainicjuj XRReferenceSpace
XRReferenceSpace opisuje system współrzędnych używany w przypadku obiektów w świecie wirtualnym. Tryb 'local' najlepiej sprawdza się w przypadku środowisk AR, w których przestrzeń odniesienia ma punkt początkowy w pobliżu użytkownika i zapewnia stabilne śledzenie.
Zainicjuj this.localReferenceSpace w onSessionStarted() za pomocą tego kodu:
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
Definiowanie pętli animacji
- Użyj
XRSessionrequestAnimationFrame, aby rozpocząć pętlę renderowania podobną dowindow.requestAnimationFrame.
W każdej klatce wywoływana jest funkcja onXRFrame z sygnaturą czasową i obiektem XRFrame.
- Dokończ wdrażanie usługi
onXRFrame. Gdy klatka zostanie narysowana, dodaj do kolejki następne żądanie:
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
- Dodaj kod, aby skonfigurować środowisko graficzne. Dodaj na dole
onXRFrame:
// Bind the graphics framebuffer to the baseLayer's framebuffer.
const framebuffer = this.xrSession.renderState.baseLayer.framebuffer;
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
this.renderer.setFramebuffer(framebuffer);
- Aby określić pozę widza, użyj
XRFrame.getViewerPose(). TenXRViewerPoseopisuje położenie i orientację urządzenia w przestrzeni. Zawiera też tablicęXRView, która opisuje każdy punkt widzenia, z którego scena powinna być renderowana, aby prawidłowo wyświetlać się na bieżącym urządzeniu. W przypadku stereoskopowej rzeczywistości wirtualnej są 2 widoki (po jednym na każde oko), a urządzenia AR mają tylko 1 widok.
Informacje wpose.viewssą najczęściej używane do konfigurowania macierzy widoku i macierzy projekcji wirtualnej kamery. Wpływa to na sposób rozmieszczenia sceny w 3D. Po skonfigurowaniu kamery można renderować scenę. - Dodaj na dole
onXRFrame:
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(this.localReferenceSpace);
if (pose) {
// In mobile AR, we only have one view.
const view = pose.views[0];
const viewport = this.xrSession.renderState.baseLayer.getViewport(view);
this.renderer.setSize(viewport.width, viewport.height);
// Use the view's transform matrix and projection matrix to configure the THREE.camera.
this.camera.matrix.fromArray(view.transform.matrix);
this.camera.projectionMatrix.fromArray(view.projectionMatrix);
this.camera.updateMatrixWorld(true);
// Render the scene with THREE.WebGLRenderer.
this.renderer.render(this.scene, this.camera);
}
Przetestuj
Uruchom aplikację. Na urządzeniu deweloperskim otwórz work/index.html. Powinien pojawić się przekaz z kamery z kostkami unoszącymi się w przestrzeni, których perspektywa zmienia się wraz z ruchem urządzenia. Śledzenie staje się dokładniejsze, gdy się poruszasz, więc sprawdź, co najlepiej sprawdza się w Twoim przypadku i na Twoim urządzeniu.

Jeśli masz problemy z uruchomieniem aplikacji, zapoznaj się z sekcjami Wprowadzenie i Konfigurowanie środowiska programistycznego.
4. Dodawanie siatki celowniczej
Po skonfigurowaniu podstawowej sceny AR możesz zacząć wchodzić w interakcje z rzeczywistym światem za pomocą testu pozycji wskaźnika. W tej sekcji zaprogramujesz test pozycji wskaźnika i użyjesz go do znalezienia powierzchni w rzeczywistym świecie.
Informacje o teście pozycji wskaźnika
Test pozycji wskaźnika to zwykle sposób na wyznaczenie prostej linii z punktu w przestrzeni w określonym kierunku i sprawdzenie, czy przecina ona jakieś interesujące obiekty. W tym przykładzie kierujesz urządzenie na miejsce w rzeczywistym świecie. Wyobraź sobie promień światła wychodzący z aparatu urządzenia i kierujący się prosto w fizyczny świat przed nim.
Interfejs WebXR Device API informuje, czy promień przecinał jakieś obiekty w rzeczywistym świecie, co jest określane przez podstawowe funkcje AR i rozumienie świata.

Poproś o XRSession z dodatkowymi funkcjami
Aby przeprowadzić testy trafień, podczas wysyłania żądania XRSession wymagane są dodatkowe funkcje.
- W
app.jsznajdźnavigator.xr.requestSession. - Dodaj funkcje
"hit-test"i"dom-overlay"jakorequiredFeatures w ten sposób:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"]
});
- Skonfiguruj nakładkę DOM. Nałóż element
document.bodyna obraz z kamery AR w ten sposób:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"],
domOverlay: { root: document.body }
});
Dodawanie prompta dotyczącego ruchu
ARCore działa najlepiej, gdy ma wystarczającą wiedzę o otoczeniu. Jest to możliwe dzięki procesowi jednoczesnej lokalizacji i mapowania (SLAM), w którym do obliczania zmiany lokalizacji i charakterystyki środowiska używane są wizualnie odrębne punkty charakterystyczne.
Użyj "dom-overlay" z poprzedniego kroku, aby wyświetlić prompt ruchu na strumieniu z kamery.
Dodaj <div> do index.html o identyfikatorze stabilization. Ten <div> wyświetla animację przedstawiającą stan stabilizacji i zachęca użytkowników do poruszania się z urządzeniem, aby usprawnić proces SLAM. Wyświetla się, gdy użytkownik korzysta z AR, i jest ukryty, gdy siatka celownicza znajdzie powierzchnię. Jest to kontrolowane przez klasy <body>.
<div id="stabilization"></div>
</body>
</html>
Dodawanie siatki celowniczej
Użyj siatki celowniczej, aby wskazać miejsce, na które jest skierowany widok urządzenia.
- W
app.jszastąp wywołanieDemoUtils.createCubeScene()wsetupThreeJs()pustym ciągiemThree.Scene().
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
}
- Wypełnij nową scenę obiektem reprezentującym punkt kolizji. Podana
Reticleklasa obsługuje wczytywanie modelu siatki celowniczej wshared/utils.js. - Dodaj
Reticledo sceny wsetupThreeJs():
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
this.reticle = new Reticle();
this.scene.add(this.reticle);
}
Aby przeprowadzić test pozycji wskaźnika, użyj nowego elementu XRReferenceSpace. Ta przestrzeń odniesienia wskazuje nowy układ współrzędnych z perspektywy widza, aby utworzyć promień, który jest zgodny z kierunkiem oglądania. Ten układ współrzędnych jest używany w XRSession.requestHitTestSource(), które może obliczać testy trafień.
- Dodaj do pliku
onSessionStarted()wapp.jste informacje:
async onSessionStarted() {
// ...
// Setup an XRReferenceSpace using the "local" coordinate system.
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
// Add these lines:
// Create another XRReferenceSpace that has the viewer as the origin.
this.viewerSpace = await this.xrSession.requestReferenceSpace("viewer");
// Perform hit testing using the viewer as origin.
this.hitTestSource = await this.xrSession.requestHitTestSource({ space: this.viewerSpace });
// ...
}
- Użyj tego
hitTestSource, aby przeprowadzać test pozycji wskaźnika w każdej klatce:- Jeśli test pozycji wskaźnika nie przyniesie żadnych wyników, oznacza to, że ARCore nie miał wystarczająco dużo czasu, aby poznać otoczenie. W takim przypadku poproś użytkownika o przesunięcie urządzenia za pomocą stabilizacji
<div>. - Jeśli pojawią się wyniki, przesuń celownik w to miejsce.
- Jeśli test pozycji wskaźnika nie przyniesie żadnych wyników, oznacza to, że ARCore nie miał wystarczająco dużo czasu, aby poznać otoczenie. W takim przypadku poproś użytkownika o przesunięcie urządzenia za pomocą stabilizacji
- Zmodyfikuj
onXRFrame, aby przesunąć siatkę celowniczą:
onXRFrame = (time, frame) => {
// ... some code omitted ...
this.camera.updateMatrixWorld(true);
// Add the following:
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
if (!this.stabilized && hitTestResults.length > 0) {
this.stabilized = true;
document.body.classList.add("stabilized");
}
if (hitTestResults.length > 0) {
const hitPose = hitTestResults[0].getPose(this.localReferenceSpace);
// update the reticle position
this.reticle.visible = true;
this.reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
this.reticle.updateMatrixWorld(true);
}
// More code omitted.
}

Dodawanie działania po dotknięciu ekranu
XRSession może emitować zdarzenia na podstawie interakcji użytkownika za pomocą zdarzenia select, które reprezentuje główną akcję. W WebXR na urządzeniach mobilnych główną czynnością jest kliknięcie ekranu.
- Dodaj detektor zdarzeń
selectu dołu plikuonSessionStarted:
this.xrSession.addEventListener("select", this.onSelect);
W tym przykładzie dotknięcie ekranu powoduje umieszczenie słonecznika w celowniku.
- Utwórz implementację interfejsu
onSelectw klasieApp:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
}
}
Testowanie aplikacji
Utworzono siatkę celowniczą, którą można wycelować za pomocą urządzenia, korzystając z testów trafień. Po kliknięciu ekranu powinna pojawić się możliwość umieszczenia słonecznika w miejscu wskazanym przez siatkę celowniczą.
- Po uruchomieniu aplikacji powinien być widoczny celownik śledzący powierzchnię podłogi. Jeśli nie, powoli rozejrzyj się dookoła, poruszając telefonem.
- Gdy zobaczysz siatkę celowniczą, kliknij ją. Na górze powinien znajdować się słonecznik. Może być konieczne poruszanie się, aby platforma AR mogła lepiej wykrywać powierzchnie w świecie rzeczywistym. Słabe oświetlenie i powierzchnie bez cech charakterystycznych obniżają jakość rozpoznawania sceny i zwiększają prawdopodobieństwo, że nie zostanie znaleziony żaden wynik. Jeśli napotkasz problemy, zapoznaj się z kodem
step-04/app.js, aby zobaczyć działający przykład tego kroku.

5. Dodawanie cieni
Tworzenie realistycznej sceny obejmuje elementy takie jak odpowiednie oświetlenie i cienie na obiektach cyfrowych, które zwiększają realizm i immersję w scenie.
Oświetlenie i cienie są obsługiwane przez three.js. Możesz określić, które światła mają rzucać cienie, które materiały mają je odbierać i renderować oraz które siatki mogą rzucać cienie. Scena tej aplikacji zawiera światło, które rzuca cień, oraz płaską powierzchnię do renderowania tylko cieni.
- Włącz cienie na
three.jsWebGLRenderer. Po utworzeniu renderera ustaw te wartości w jego polushadowMap:
setupThreeJs() {
...
this.renderer = new THREE.WebGLRenderer(...);
...
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
...
}
Przykładowa scena utworzona w DemoUtils.createLitScene() zawiera obiekt o nazwie shadowMesh, czyli płaską, poziomą powierzchnię, która renderuje tylko cienie. Początkowo ta powierzchnia ma pozycję Y wynoszącą 10 000 jednostek. Po umieszczeniu słonecznika przesuń ikonę shadowMesh na wysokość powierzchni w rzeczywistym świecie, tak aby cień kwiatu był renderowany na ziemi.
- W
onSelectpo dodaniuclonedo sceny dodaj kod, aby zmienić położenie płaszczyzny cienia:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
const shadowMesh = this.scene.children.find(c => c.name === "shadowMesh");
shadowMesh.position.y = clone.position.y;
}
}
Przetestuj
Po umieszczeniu słonecznika powinien być widoczny jego cień. Jeśli napotkasz problemy, zapoznaj się z kodem final/app.js, aby zobaczyć działający przykład tego kroku.

6. Dodatkowe materiały
Gratulacje! To już koniec tego ćwiczenia z zakresu AR z użyciem WebXR.

