Ti diamo il benvenuto nel Web immersivo

Per "web immersivo" si intendono esperienze virtuali ospitate tramite il browser. L'intera esperienza di realtà virtuale è emersi nel browser o nei visori compatibili con la realtà virtuale.

Joe Medley
Joe Medley

Per web immersivo si intendono esperienze virtuali ospitate tramite il browser. Ciò riguarda l'intera esperienza di realtà virtuale (VR) esposta nel browser o con visori abilitati per la realtà virtuale come Daydream di Google, Oculus Rift, Samsung Gear VR, HTC Vive e auricolari per realtà mista Windows, nonché esperienze di realtà aumentata sviluppate per dispositivi mobili abilitati per AR.

Le esperienze immersive vengono utilizzate in due termini, ma vanno considerate come uno spettro che va dalla realtà completa a un ambiente VR completamente immersivo, con diversi livelli di AR.

Esempi di esperienze immersive includono:

  • Video immersivi a 360°
  • Video tradizionali in 2D (o 3D) presentati in un ambiente immersivo.
  • Visualizzazioni di dati
  • Acquisto di articoli per la casa
  • Arte
  • Qualcosa di interessante a cui non ha ancora pensato nessuno

Come ci arrivo?

Il web immersivo è disponibile da quasi un anno in forma embrionale. Ciò è stato possibile tramite l'API WebVR 1.1, che è disponibile in una prova delle origini a partire da Chrome 62. L'API è supportata anche da Firefox ed Edge, nonché da un polyfill per Safari.

Ma è ora di andare avanti.

La prova dell'origine è terminata il 24 luglio 2018 e la specifica è stata sostituita dall'API WebXR Device e da una nuova prova dell'origine.

Cosa è successo a WebVR 1.1?

Abbiamo imparato molto da WebVR 1.1, ma nel tempo è emerso chiaramente che erano necessarie alcune modifiche importanti per supportare i tipi di applicazioni che gli sviluppatori volevano creare. L'elenco completo delle lezioni apprese è troppo lungo per essere trattato qui, ma include problemi come l'associazione dell'API al thread JavaScript principale, le troppe opportunità per gli sviluppatori di configurare configurazioni palesemente errate e gli utilizzi comuni come la finestra magica come effetto collaterale piuttosto che una funzionalità intenzionale. La finestra magica è una tecnica per visualizzare contenuti immersivi senza un paio di cuffie in cui l'app esegue il rendering di una singola visualizzazione in base al sensore di orientamento del dispositivo.

Il nuovo design facilita implementazioni e miglioramenti significativi delle prestazioni. Allo stesso tempo, stavano emergendo l'AR e altri casi d'uso ed è diventato importante che l'API fosse estendibile per supportare questi casi in futuro.

L'API WebXR Device è stata progettata e denominata tenendo conto di questi casi d'uso ampliati e offre un percorso migliore. Gli implementatori di WebVR si sono impegnati a eseguire la migrazione all'API WebXR Device.

Che cos'è l'API WebXR Device?

Come la specifica WebVR precedente, l'API WebXR Device è un prodotto di Immersive Web Community Group che ha collaborato da Google, Microsoft, Mozilla e altri ancora. La "X in XR" è intesa come una sorta di variabile algebrica che indica qualsiasi cosa nello spettro delle esperienze immersive. È disponibile nella prova dell'origine menzionata in precedenza, oltre che tramite un polyfill.

Quando questo articolo è stato pubblicato originariamente durante il periodo beta di Chrome 67, erano attivate solo le funzionalità VR. La realtà aumentata è arrivata in Chrome 69. Scopri di più in Realtà aumentata per il web.

Questa nuova API offre molte altre informazioni di quante ne servano in un articolo come questo. Voglio darti abbastanza per iniziare a dare un senso agli esempi di WebXR. Puoi trovare ulteriori informazioni sia nel video esplicativo originale sia nella nostra Guida per early adopter del web immersiva. Lo amplierò quest'ultimo con il progredire della prova dell'origine. Non esitare a risolvere i problemi o a inviare richieste di pull.

In questo articolo, parlerò dell'avvio, dell'interruzione e dell'esecuzione di una sessione XR, oltre ad alcune nozioni di base sull'elaborazione dell'input.

Non parlerò di come disegnare i contenuti AR/VR sullo schermo. L'API WebXR Device non fornisce funzionalità di rendering delle immagini. Dipende da te. Il disegno viene realizzato utilizzando le API WebGL. Puoi raggiungere questo obiettivo se sei veramente ambizioso. Tuttavia, consigliamo di usare un framework. Gli esempi web immersivi ne utilizzano uno creato appositamente per le demo chiamato Cottontail. Three.js supporta WebXR da maggio. Non ho sentito parlare di A-Frame.

Avvio ed esecuzione di un'app

La procedura di base è la seguente:

  1. Richiedi un dispositivo XR.
  2. Se è disponibile, richiedi una sessione XR. Se vuoi che l'utente aggiunga le cuffie, si parla di sessione immersiva e per accedere è necessario un gesto.
  3. Utilizza la sessione per eseguire un loop di rendering che fornisce 60 frame immagine al secondo. Disegna contenuti appropriati sullo schermo in ogni frame.
  4. Esegui il loop di rendering finché l'utente non decide di uscire.
  5. Termina la sessione XR.

Diamo un'occhiata a questo aspetto più nel dettaglio e includiamo del codice. Non sarai in grado di eseguire un'app da quello che sto per mostrarti. Ma, di nuovo, solo per dare un'idea.

Richiedi un dispositivo XR

Riconoscerai il codice di rilevamento delle funzionalità standard. Puoi aggregare questo elemento in una funzione chiamata ad esempio checkForXR().

Se non utilizzi una sessione immersiva, puoi saltare la pubblicità della funzionalità e ricevere un gesto dell'utente e passare direttamente alla richiesta di una sessione. Una sessione immersiva richiede l'uso di cuffie. Una sessione non immersiva mostra semplicemente i contenuti sullo schermo del dispositivo. La prima è ciò che la maggior parte delle persone pensa quando fa riferimento alla realtà virtuale o alla realtà aumentata. Quest'ultimo a volte viene chiamato "finestra magica".

if (navigator.xr) {
    navigator.xr.requestDevice()
    .then(xrDevice => {
    // Advertise the AR/VR functionality to get a user gesture.
    })
    .catch(err => {
    if (err.name === 'NotFoundError') {
        // No XRDevices available.
        console.error('No XR devices available:', err);
    } else {
        // An error occurred while requesting an XRDevice.
        console.error('Requesting XR device failed:', err);
    }
    })
} else{
    console.log("This browser does not support the WebXR API.");
}

Richiedi una sessione XR

Ora che abbiamo il dispositivo e il gesto dell'utente, è il momento di avviare una sessione. Per creare una sessione, il browser ha bisogno di una tela su cui disegnare.

xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
    // The immersive option is optional for non-immersive sessions; the value
    //   defaults to false.
    immersive: false,
    outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Use a WebGL context as a base layer.
    xrSession.baseLayer = new XRWebGLLayer(session, gl);
    // Start the render loop
})

Esegui il loop di rendering

Il codice per questo passaggio richiede un po' di tempo. Per sgranchire le cose, ti vincerò un bel po' di parole. Se vuoi dare un'occhiata al codice finale, prosegui per esaminarlo rapidamente, quindi torna indietro per la spiegazione completa. Ci sono molte cose che potresti non essere in grado di dedurre.

Il processo di base per un loop di rendering è il seguente:

  1. Richiedi un frame dell'animazione.
  2. Query per la posizione del dispositivo.
  3. Disegna contenuti sulla posizione del dispositivo in base alla sua posizione.
  4. Svolgere le operazioni necessarie per i dispositivi di input.
  5. Ripeti l'operazione 60 volte al secondo finché l'utente non decide di uscire.

Richiedi un frame per la presentazione

La parola "frame" ha diversi significati in un contesto Web XR. Il primo è il frame di riferimento che definisce da dove viene calcolata l'origine del sistema di coordinate e cosa succede a quell'origine quando il dispositivo si sposta. (La visualizzazione rimane invariata quando l'utente si sposta o cambia come nella vita reale?)

Il secondo tipo di frame è il frame di presentazione, rappresentato da un oggetto XRFrame. Questo oggetto contiene le informazioni necessarie per visualizzare sul dispositivo un singolo fotogramma di una scena AR/VR. Questo è un po' confusa perché il frame della presentazione viene recuperato chiamando requestAnimationFrame(). Ciò lo rende compatibile con window.requestAnimationFrame().

Prima di dare qualche altra informazione da assimilare, ti offrirò del codice. L'esempio di seguito mostra come viene avviato e gestito il loop di rendering. Nota il duplice utilizzo dei frame per le parole. E nota la chiamata ricorsiva a requestAnimationFrame(). Questa funzione verrà chiamata 60 volte al secondo.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    // Process the frame.
    xrFrame.session.requestAnimationFrame(onFrame);
    }
});

Pose

Prima di disegnare qualsiasi cosa sullo schermo, devi sapere dove punta il display e devi accedere allo schermo. In generale, la posizione e l'orientamento di un oggetto in AR/VR sono definiti in posa. Sia gli spettatori che i dispositivi di input mettono in posa. (Parlerò dei dispositivi di input più tardi). Le posizioni del visualizzatore e del dispositivo di input sono definite come una matrice 4 x 4 archiviata in un elemento Float32Array nell'ordine principale della colonna. Per ottenere la posa dello spettatore, richiama XRFrame.getDevicePose() sull'oggetto frame dell'animazione corrente. Fai sempre delle prove per vedere se sei tornato in posa. Se si è verificato un problema, non vuoi apparire sullo schermo.

let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
    // Draw something to the screen.
}

Visualizzazioni

Dopo aver controllato la posa, è il momento di disegnare qualcosa. L'oggetto a cui aggreghi è chiamato visualizzazione (XRView). È qui che diventa importante il tipo di sessione. Le visualizzazioni vengono recuperate dall'oggetto XRFrame come array. Se ti trovi in una sessione non immersiva, l'array ha una sola vista. Se ti trovi in una sessione immersiva, l'array ne ha due, uno per ogni occhio.

for (let view of xrFrame.views) {
    // Draw something to the screen.
}

Questa è una differenza importante tra WebXR e altri sistemi immersivi. Sebbene possa sembrare inutile eseguire l'iterazione in una sola vista, questo ti consente di avere un unico percorso di rendering per diversi dispositivi.

L'intero loop di rendering

Se metto tutto insieme, ottengo il codice che segue. Ho lasciato un segnaposto per i dispositivi di input, di cui parlerò in una sezione successiva.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    let pose = xrFrame.getDevicePose(xrFrameOfRef);
    if (pose) {
        for (let view of xrFrame.views) {
        // Draw something to the screen.
        }
    }
    // Input device code will go here.
    frame.session.requestAnimationFrame(onFrame);
    }
}

Termina la sessione XR

Una sessione XR può terminare per diversi motivi, ad esempio per terminare con il tuo codice tramite una chiamata a XRSession.end(). Altre cause sono lo scollegamento delle cuffie o un'altra applicazione che ne prende il controllo. Questo è il motivo per cui un'applicazione che funziona bene dovrebbe monitorare l'evento finale e, quando si verifica, ignorare gli oggetti sessione e renderer. Una volta terminata, una sessione XR non può essere ripresa.

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('end', onSessionEnd);
});

// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
    xrSession = null;

    // Ending the session stops executing callbacks passed to the XRSession's
    // requestAnimationFrame(). To continue rendering, use the window's
    // requestAnimationFrame() function.
    window.requestAnimationFrame(onDrawFrame);
}

Come funziona l'interazione?

Come per la durata dell'applicazione, ora voglio darti un'idea di come interagire con gli oggetti in AR o VR.

L'API WebXR Device adotta un approccio "point and click" per l'input utente. Con questo approccio, ogni origine di input dispone di un raggio puntatore definito per indicare il punto di punta di un dispositivo di input e di eventi per indicare quando è stato selezionato qualcosa. L'app traccia il raggio di puntamento e mostra dove è puntato. Quando l'utente fa clic sul dispositivo di input, vengono attivati gli eventi, nello specifico select, selectStart e selectEnd. La tua app determina su quali elementi è stato fatto clic e risponde in modo appropriato.

Il dispositivo di input e il raggio puntatore

Per gli utenti, il raggio puntatore è solo una debole linea tra il controller e qualsiasi cosa su cui punti. ma la tua app deve disegnarla. Ciò significa avere la posa del dispositivo di input e tracciare una linea dalla sua posizione a un oggetto nello spazio AR/VR. Il processo è più o meno simile al seguente:

let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
    let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
    if (!inputPose) {
    continue;
    }
    if (inputPose.gripMatrix) {
    // Render a virtual version of the input device
    //   at the correct position and orientation.
    }
    if (inputPose.pointerMatrix) {
    // Draw a ray from the gripMatrix to the pointerMatrix.
    }
}

Questa è una versione semplificata dell'esempio di monitoraggio dell'input di Immersive Web Community Group. Come per il rendering dei fotogrammi, disegnare il raggio puntatore e il dispositivo spetta a te. Come accennato in precedenza, questo codice deve essere eseguito come parte del loop di rendering.

Selezione di elementi nello spazio virtuale

Indicare semplicemente gli elementi in AR/VR è piuttosto inutile. Per poter fare qualcosa di utile, gli utenti devono poter selezionare elementi. L'API WebXR Device fornisce tre eventi per rispondere alle interazioni degli utenti: select, selectStart e selectEnd. Hanno una particolarità che non mi aspettavo: ti dicono solo che è stato fatto clic su un dispositivo di input. Non indicano su quale elemento dell'ambiente è stato fatto clic. I gestori di eventi vengono aggiunti all'oggetto XRSession e dovrebbero essere aggiunti non appena sono disponibili.

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('selectstart', onSelectStart);
    xrSession.addEventListener('selectend', onSelectEnd);
    xrSession.addEventListener('select', onSelect);
});

Questo codice si basa su un esempio di selezione dell'input, nel caso tu voglia maggiori informazioni.

Per capire su cosa è stato fatto clic, usa una posa. (Sei sorpreso? Non credevo.) I dettagli sono specifici della tua app o di qualsiasi framework che utilizzi e quindi esulano dall'ambito di questo articolo. L'approccio di Cottontail è nell'esempio di selezione dell'input.

function onSelect(ev) {
    let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
    if (!inputPose) {
    return;
    }
    if (inputPose.pointerMatrix) {
    // Figure out what was clicked and respond.
    }
}

Conclusione: guardare al futuro

Come ho detto prima, la realtà aumentata è prevista in Chrome 69 (per Canary, nel giugno 2018). Ciononostante, ti consiglio di provare le ultime novità. Abbiamo bisogno di un feedback per migliorarla. Segui i progressi osservando ChromeStatus.com per WebXR Hit Test. Puoi anche seguire gli ancoraggi WebXR che miglioreranno il monitoraggio della posa.