1. Prima di iniziare
Questo codelab illustra un esempio di creazione di un'app web AR. Utilizza JavaScript per eseguire il rendering di modelli 3D che sembrano esistenti nel mondo reale.
Utilizzi l'API WebXR Device che combina AR e funzionalità di realtà virtuale (VR). Ti concentrerai sulle estensioni AR per l'API WebXR Device per creare una semplice app AR che viene eseguita sul web interattivo.
Che cos'è l'AR?
AR è un termine di solito utilizzato per descrivere la fusione tra grafica generata al computer e mondo reale. Nel caso dell'AR basata su telefono, ciò significa posizionare in modo convincente la grafica del computer su un feed della videocamera in diretta. Affinché questo effetto rimanga realistico mentre lo smartphone si sposta per il mondo, il dispositivo abilitato per l'AR deve comprendere il mondo attraverso il quale si muove e determinare la sua posa (posizione e orientamento) nello spazio 3D. Queste operazioni potrebbero includere il rilevamento delle superfici e una stima dell'illuminazione dell'ambiente.
L'AR è diventato ampiamente utilizzato nelle app dopo il rilascio di ARCore di Google e ARKit di Apple, sia per i filtri per i selfie sia per i giochi basati su AR.
Cosa creerai
In questo codelab, creerai un'app web che posiziona un modello nel mondo reale utilizzando la realtà aumentata. La tua app sarà in grado di:
- Utilizza i sensori del dispositivo target per determinarne e monitorarne la posizione e l'orientamento rispetto al mondo reale
- Eseguire il rendering di un modello 3D composto sopra la visione in diretta della videocamera
- Esegui test sugli hit per posizionare oggetti sopra le superfici scoperte nel mondo reale
Obiettivi didattici
- Come utilizzare l'API WebXR Device
- Come configurare una scena AR di base
- Come trovare una superficie usando i test degli hit AR
- Come caricare ed eseguire il rendering di un modello 3D sincronizzato con il feed della videocamera del mondo reale
- Come eseguire il rendering delle ombre in base al modello 3D
Questo codelab è incentrato sulle API AR. Concetti e blocchi di codice non pertinenti sono trattati solo superficialmente e sono forniti nel codice del repository corrispondente.
Che cosa ti serve
- Una workstation per la programmazione e l'hosting di contenuti web statici
- Dispositivo Android compatibile con ARCore con Android 8.0 Oreo
- Google Chrome
- Google Play Services per AR installato (Chrome ti chiede automaticamente di installarlo sui dispositivi compatibili)
- Un server web a tua scelta
- Cavo USB per collegare il dispositivo AR alla workstation
- Il codice campione
- Un editor di testo
- Conoscenza di base di HTML, CSS, JavaScript e degli Strumenti per sviluppatori di Google Chrome
Fai clic su Prova sul tuo dispositivo AR per provare il primo passaggio di questo codelab. Se visualizzi una pagina con il messaggio "Il tuo browser non dispone di funzionalità AR", verifica che sul tuo dispositivo Android sia installato Google Play Services per AR.
2. Configurazione dell'ambiente di sviluppo
Scarica il codice
- Fai clic sul link seguente per scaricare tutto il codice per questo codelab sulla tua workstation:
- Apri il file ZIP scaricato. Verrà aperta una cartella principale (
ar-with-webxr-master
), che contiene le directory di diversi passaggi di questo codelab, insieme a tutte le risorse di cui hai bisogno.
Le cartelle step-03
e step-04
contengono lo stato finale desiderato del terzo e del quarto passaggio di questo codelab, nonché il risultato final
. che vengono utilizzate come riferimento.
Svolgi tutte le attività di programmazione nella directory work
.
Installa server web
- Sei libero di utilizzare il tuo server web. Se non ne hai ancora configurato uno, in questa sezione viene spiegato in dettaglio come configurare il server web per Chrome.
Se l'app non è ancora installata sulla tua workstation, puoi installarla dal Chrome Web Store.
- Dopo aver installato l'app server web per Chrome, vai a
chrome://apps
e fai clic sull'icona del server web:
Viene visualizzata questa finestra di dialogo, che ti consente di configurare il server web locale:
- Fai clic su scegli cartella e seleziona la cartella
ar-with-webxr-master
. Questo ti consente di pubblicare il lavoro in corso tramite l'URL evidenziato nella finestra di dialogo del server web (nella sezione URL server web). - In Opzioni (richiede riavvio), seleziona la casella di controllo Mostra automaticamente index.html.
- Imposta Server web su Arresta, quindi seleziona Avviato.
- Verifica che venga visualizzato almeno uno o più URL del server web: http://127.0.0.1:8887, l'URL localhost predefinito.
Configura port forwarding
Configura il tuo dispositivo AR in modo che acceda alla stessa porta sulla workstation quando visiti localhost:8887.
- Sulla workstation di sviluppo, vai a chrome://inspect e fai clic su Port forwarding...:
- Utilizza la finestra di dialogo Impostazioni di port forwarding per inoltrare la porta 8887 a localhost:8887.
- Seleziona la casella di controllo Attiva port forwarding:
Verificare la configurazione
Testa la tua connessione:
- Collega il dispositivo AR alla workstation con un cavo USB.
- Sul dispositivo AR in Chrome, inserisci http://localhost:8887 nella barra degli indirizzi. Il dispositivo AR dovrebbe inoltrare questa richiesta al server web della workstation di sviluppo. Dovresti vedere una directory di file.
- Sul dispositivo AR, fai clic su
step-03
per caricare il filestep-03/index.html
nel browser.
Dovresti vedere una pagina contenente un pulsante Avvia realtà aumentata. | Tuttavia, se viene visualizzata la pagina di errore Browser non supportato, è probabile che il tuo dispositivo non sia compatibile. |
La connessione al server web dovrebbe funzionare con il dispositivo AR.
- Fai clic su Avvia realtà aumentata. È possibile che ti venga richiesto di installare ARCore.
La prima volta che esegui un'app AR viene visualizzata una richiesta di autorizzazione della fotocamera.
→
Quando è tutto pronto, dovresti vedere una scena di cubi sovrapposti sopra il feed di una videocamera. La comprensione della scena migliora poiché più parti del mondo vengono analizzate dalla fotocamera, quindi muoversi può contribuire a stabilizzare le cose.
3. Configura WebXR
In questo passaggio, imparerai a configurare una sessione WebXR e una scena AR di base. Nella pagina HTML vengono forniti gli stili CSS e JavaScript per attivare le funzionalità AR di base. Questo accelera il processo di configurazione, consentendo al codelab di concentrarsi sulle funzionalità AR.
La pagina HTML
Crei un'esperienza AR in una pagina web tradizionale utilizzando tecnologie web esistenti. In questa esperienza, viene utilizzato un canvas di rendering a schermo intero, in modo che il file HTML non sia eccessivamente complesso.
Per avviare le funzionalità AR è necessario un gesto dell'utente, perciò esistono alcuni componenti Material Design per la visualizzazione del pulsante Avvia AR e del messaggio del browser non supportato.
Il file index.html
già presente nella directory work
dovrebbe avere un aspetto simile al seguente. Si tratta di un sottoinsieme dei contenuti effettivi, non copiare questo codice nel tuo file.
<!-- 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>
Apri il codice JavaScript della chiave
Il punto di partenza della tua app è app.js
. Questo file fornisce un boilerplate per la configurazione di un'esperienza AR.
La directory di lavoro include già il codice dell'app (app.js
).
Verificare il supporto di WebXR e AR
Prima che un utente possa lavorare con l'AR, verifica che esistano navigator.xr
e le funzionalità XR necessarie. L'oggetto navigator.xr
è il punto di ingresso dell'API WebXR Device, quindi dovrebbe esistere se il dispositivo è compatibile. Verifica inoltre che la modalità di sessione "immersive-ar"
sia supportata.
Se non ci sono problemi, facendo clic sul pulsante Entra in realtà aumentata si tenta di creare una sessione XR. In caso contrario, viene chiamato (in shared/utils.js
) onNoXRDevice()
e viene visualizzato un messaggio che indica la mancanza di supporto AR.
Questo codice è già presente in app.js
, quindi non è necessario apportare modifiche.
(async function() {
if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) {
document.getElementById("enter-ar").addEventListener("click", activateXR)
} else {
onNoXRDevice();
}
})();
Richiedi XRSession
Quando fai clic su Attiva realtà aumentata, il codice chiama activateXR()
. Verrà avviata l'esperienza AR.
- Trova la funzione
activateXR()
inapp.js
. Alcuni codici sono stati omessi:
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = /* TODO */;
// Omitted for brevity
}
Il punto di accesso a WebXR è tramite XRSystem.requestSession()
. Usa la modalità immersive-ar
per consentire la visualizzazione dei contenuti visualizzati in un ambiente reale.
- Inizializza
this.xrSession
utilizzando la modalità"immersive-ar"
:
activateXR = async () => {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = await navigator.xr.requestSession("immersive-ar");
// ...
}
Inizializza un XRReferenceSpace
Un simbolo XRReferenceSpace
descrive il sistema di coordinate utilizzato per gli oggetti all'interno del mondo virtuale. La modalità 'local'
è più adatta per un'esperienza AR, con uno spazio di riferimento che ha un'origine vicina allo spettatore e un monitoraggio stabile.
Inizializza this.localReferenceSpace
in onSessionStarted()
con il seguente codice:
this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");
Definisci un loop di animazione
- Usa l'elemento
requestAnimationFrame
diXRSession
per avviare un loop di rendering, simile awindow.requestAnimationFrame
.
Su ogni frame, onXRFrame
viene chiamato con un timestamp e un XRFrame.
- Completa l'implementazione di
onXRFrame
. Quando viene disegnato un frame, accoda la richiesta successiva aggiungendo:
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
- Aggiungi il codice per configurare l'ambiente grafico. Aggiungi in fondo a
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);
- Per determinare la posa dello spettatore, utilizza
XRFrame.getViewerPose()
. Questa classeXRViewerPose
descrive la posizione e l'orientamento del dispositivo nello spazio. Contiene anche un array diXRView
, che descrive ogni punto di osservazione da cui deve essere eseguito il rendering della scena per poter essere visualizzata correttamente sul dispositivo corrente. Mentre la realtà virtuale stereoscopica ha due visualizzazioni (una per ogni occhio), i dispositivi AR hanno una sola visualizzazione.
Le informazioni inpose.views
vengono usate per lo più per configurare la matrice di visualizzazione e la matrice di proiezione della videocamera virtuale. Questo influisce sulla disposizione della scena in 3D. Dopo avere configurato la videocamera, è possibile eseguire il rendering della scena. - Aggiungi in fondo a
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);
}
Testa
Eseguire l'app; sul tuo dispositivo di sviluppo, visita work/index.html
. Dovresti vedere il feed della videocamera con dei cubi che fluttuano nello spazio la cui prospettiva cambia mentre muovi il dispositivo. Il rilevamento migliora man mano che ti sposti, quindi scopri cosa funziona per te e il tuo dispositivo.
In caso di problemi di esecuzione dell'app, consulta le sezioni Introduzione e Configurare l'ambiente di sviluppo.
4. Aggiungere un reticolo di targeting
Dopo aver configurato una scena AR di base, è il momento di iniziare a interagire con il mondo reale utilizzando un test di successo. In questa sezione, programma un hit test e lo userai per trovare una superficie nel mondo reale.
Informazioni su un test di hit
Un test di hit è generalmente un modo per lanciare una linea retta da un punto dello spazio in una direzione e determinare se si interseca con un oggetto di interesse. In questo esempio, il dispositivo viene puntato verso una località del mondo reale. Immagina un raggio che viaggia dalla fotocamera del tuo dispositivo e si avvicini direttamente al mondo fisico di fronte a quest'ultimo.
L'API WebXR Device ti consente di sapere se questo raggio ha intersecato oggetti nel mondo reale, determinato dalle funzionalità AR sottostanti e dalla comprensione del mondo.
Richiedi un XRSession
con funzionalità extra
Per eseguire hit test, sono necessarie funzionalità aggiuntive quando richiedi l'XRSession
.
- In
app.js
, individuanavigator.xr.requestSession
. - Aggiungi le caratteristiche
"hit-test"
e"dom-overlay"
comerequiredFeature
nel seguente modo:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"]
});
- Configura l'overlay DOM. Sovrapponi l'elemento
document.body
alla visualizzazione della fotocamera AR in questo modo:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["hit-test", "dom-overlay"],
domOverlay: { root: document.body }
});
Aggiungi un prompt di movimento
ARCore funziona al meglio quando è stata acquisita una conoscenza adeguata dell'ambiente. Questo si ottiene attraverso un processo chiamato SLAM (Localization and Mapping simultaneo) in cui punti di caratteristiche visivamente distinti vengono utilizzati per calcolare una variazione delle caratteristiche della località e dell'ambiente.
Usa l'"dom-overlay"
del passaggio precedente per visualizzare una richiesta di movimento sopra lo stream della videocamera.
Aggiungi <div>
a index.html
con ID stabilization
. Questo <div>
mostra un'animazione agli utenti che rappresenta lo stato di stabilizzazione e chiede loro di spostarsi con il dispositivo per migliorare il processo SLAM. Viene visualizzato quando l'utente si trova in AR e viene nascosto quando il reticolo trova una superficie controllata da <body>
classi.
<div id="stabilization"></div>
</body>
</html>
Aggiungi un reticolo
Utilizza un reticolo per indicare la posizione verso cui punta il campo visivo del dispositivo.
- In
app.js
, sostituisci la chiamataDemoUtils.createCubeScene()
insetupThreeJs()
con un campoThree.Scene()
vuoto.
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
}
- Compila la nuova scena con un oggetto che rappresenta il punto di collisione. La classe
Reticle
fornita gestisce il caricamento del modello del reticolo inshared/utils.js
. - Aggiungi
Reticle
alla scena insetupThreeJs()
:
setupThreeJs() {
// ...
// this.scene = DemoUtils.createCubeScene();
this.scene = DemoUtils.createLitScene();
this.reticle = new Reticle();
this.scene.add(this.reticle);
}
Per eseguire un test degli hit, utilizza un nuovo XRReferenceSpace
. Questo spazio di riferimento indica un nuovo sistema di coordinate dal punto di vista dell'utente per creare un raggio allineato alla direzione di visualizzazione. Questo sistema di coordinate viene utilizzato in XRSession.requestHitTestSource()
, che può calcolare i test di hit.
- Aggiungi il seguente codice a
onSessionStarted()
inapp.js
:
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 });
// ...
}
- Con questo
hitTestSource
, esegui un test degli hit per ogni frame:- Se non ci sono risultati per l'hit test, significa che ARCore non ha avuto tempo sufficiente per comprendere l'ambiente. In questo caso, chiedi all'utente di spostare il dispositivo utilizzando la stabilizzazione
<div>
. - Se ci sono risultati, sposta il reticolo in quella posizione.
- Se non ci sono risultati per l'hit test, significa che ARCore non ha avuto tempo sufficiente per comprendere l'ambiente. In questo caso, chiedi all'utente di spostare il dispositivo utilizzando la stabilizzazione
- Modifica
onXRFrame
per spostare il reticolo:
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.
}
Aggiungi comportamento al tocco sullo schermo
Un XRSession
può emettere eventi in base all'interazione dell'utente tramite l'evento select
, che rappresenta l'azione principale. In WebXR sui dispositivi mobili, l'azione principale è il tocco sullo schermo.
- Aggiungi un listener di eventi
select
in fondo aonSessionStarted
:
this.xrSession.addEventListener("select", this.onSelect);
In questo esempio, toccando lo schermo viene inserito un girasole in corrispondenza del reticolo.
- Crea un'implementazione per
onSelect
nella classeApp
:
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone);
}
}
Testa l'app
Hai creato un reticolo che puoi mirare utilizzando il dispositivo utilizzando gli hit test. Quando tocchi lo schermo, dovresti riuscire a posizionare un girasole nella posizione indicata dal reticolo.
- Quando esegui l'app, dovresti essere in grado di vedere un reticolo che traccia la superficie del pavimento. In caso contrario, prova a guardarti intorno lentamente con lo smartphone.
- Quando vedi il reticolo, toccalo. Ci deve essere sopra un girasole. Potrebbe essere necessario spostarsi per un po' in modo che la piattaforma AR sottostante possa rilevare meglio le superfici nel mondo reale. La scarsa illuminazione e le superfici senza funzionalità riducono la qualità della comprensione della scena e aumentano la possibilità che non venga trovato alcun hit. Se riscontri problemi, controlla il codice
step-04/app.js
per vedere un esempio funzionante di questo passaggio.
5. Aggiungi ombre
La creazione di una scena realistica comporta elementi come l'illuminazione e le ombre appropriate sugli oggetti digitali che aggiungono realismo e immersività nella scena.
Luci e ombre sono gestite da three.js
. Puoi specificare quali luci devono proiettare ombre, quali materiali ricevere e renderizzare queste ombre e quali mesh possono proiettare ombre. La scena di questa app contiene una luce che proietta un'ombra e una superficie piana per il rendering solo delle ombre.
- Attiva le ombre su
three.js
WebGLRenderer
. Dopo aver creato il renderer, imposta i seguenti valori sul relativoshadowMap
:
setupThreeJs() {
...
this.renderer = new THREE.WebGLRenderer(...);
...
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
...
}
La scena di esempio creata in DemoUtils.createLitScene()
contiene un oggetto chiamato shadowMesh
, una superficie piatta orizzontale che mostra solo ombre. Questa superficie ha inizialmente una posizione Y di 10.000 unità. Dopo aver posizionato un girasole, sposta il shadowMesh
in modo che abbia la stessa altezza della superficie reale, in modo che l'ombra del fiore venga visualizzata sul terreno reale.
- In
onSelect
, dopo aver aggiuntoclone
alla scena, aggiungi il codice per riposizionare il piano ombra:
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;
}
}
Testa
Quando posizioni un girasole, dovresti riuscire a vederlo mentre proietta un'ombra. Se riscontri problemi, controlla il codice final/app.js
per vedere un esempio funzionante di questo passaggio.
6. Risorse aggiuntive
Complimenti! Hai raggiunto la fine di questo codelab su AR utilizzando WebXR.