Si ya usaste la API de WebXR Device, ya tienes la mitad del camino recorrido.
La API de WebXR Device se lanzó el otoño pasado en Chrome 79. Como se indicó en ese momento, la implementación de la API de Chrome está en curso. Chrome se complace en anunciar que ya se completó parte del trabajo. En Chrome 81, se agregaron dos funciones nuevas:
En este artículo, se explica la realidad aumentada. Si ya usaste la API de WebXR Device, te alegrará saber que hay muy poco contenido nuevo que aprender. El ingreso a una sesión de WebXR es, en gran medida, el mismo. Ejecutar un bucle de fotogramas es en gran medida lo mismo. Las diferencias radican en las configuraciones que permiten que el contenido se muestre de manera adecuada para la realidad aumentada. Si no conoces los conceptos básicos de WebXR, deberías leer mis publicaciones anteriores sobre la API de WebXR Device o, al menos, estar familiarizado con los temas que se abordan en ellas. Debes saber cómo solicitar y entrar a una sesión, y debes saber cómo ejecutar un bucle de fotogramas.
Para obtener información sobre las pruebas de posicionamiento, consulta el artículo complementario Posicionamiento de objetos virtuales en vistas del mundo real. El código de este artículo se basa en la muestra de la Immersive AR Session (fuente de demostración) de las muestras de la API de WebXR Device de Immersive Web Working Group.
Antes de profundizar en el código, debes usar la muestra de Immersive AR Session al menos una vez. Necesitarás un teléfono Android moderno con Chrome 81 o una versión posterior.
¿Para qué sirve?
La realidad aumentada será una adición valiosa a muchas páginas web nuevas o existentes, ya que les permitirá implementar casos de uso de RA sin salir del navegador. Por ejemplo, puede ayudar a las personas a aprender en sitios educativos y permitir que los compradores potenciales visualicen objetos en su casa mientras compran.
Considera el segundo caso de uso. Imagina que simulas colocar una representación de tamaño real de un objeto virtual en una escena real. Una vez colocada, la imagen permanece en la superficie seleccionada, aparece del tamaño que tendría si el elemento real estuviera en esa superficie y permite que el usuario se mueva a su alrededor, así como acercarse o alejarse. Esto les brinda a los usuarios una comprensión más profunda del objeto que es posible con una imagen de dos dimensiones.
Me estoy adelantando un poco. Para hacer lo que describí, necesitas la funcionalidad de RA y algunos medios para detectar superficies. En este artículo, se aborda la primera opción. En el artículo complementario sobre la API de Hit Test de WebXR (vinculado más arriba), se explica lo último.
Cómo solicitar una sesión
Solicitar una sesión es muy similar a lo que ya viste antes. Primero, llama a xr.isSessionSupported()
para averiguar si el tipo de sesión que deseas está disponible en el dispositivo actual. En lugar de solicitar 'immersive-vr'
como antes, solicita '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
}
}
Como antes, esta opción habilita el botón "Enter AR". Cuando el usuario haga clic en ella, llama a xr.requestSession()
y pasa '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();
}
}
Un minimercado
Es probable que hayas notado que destaqué dos líneas en el último ejemplo de código.
Al parecer, el objeto XRSession
tiene una propiedad llamada isImmersive
. Esta es una propiedad de conveniencia que creé yo y no forma parte de la especificación. La usaré más adelante para tomar decisiones sobre qué mostrarle al usuario. ¿Por qué esta propiedad no es parte de la API? Debido a que tu app puede necesitar hacer un seguimiento de esta propiedad de manera diferente, los autores de la especificación decidieron mantener la API limpia.
Ingresa a una sesión
Recuerda cómo se veía onSessionStarted()
en mi artículo anterior:
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);
});
}
Necesito agregar algunos elementos para tener en cuenta la renderización de la realidad aumentada. Desactiva el fondo. Primero, determinaré si necesito el fondo. Este es el primer lugar en el que usaré mi propiedad de conveniencia.
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);
});
}
Espacios de referencia
En mis artículos anteriores, analicé los espacios de referencia. En el ejemplo que describo, se usan dos, así que es hora de corregir esa omisión.
Un espacio de referencia describe la relación entre el mundo virtual y el entorno físico del usuario. Para ello, hace lo siguiente:
- Especifica el origen del sistema de coordenadas que se usa para expresar posiciones en el mundo virtual.
- Especifica si se espera que el usuario se mueva dentro de ese sistema de coordenadas.
- Si ese sistema de coordenadas tiene límites preestablecidos. (En los ejemplos que se muestran aquí, no se usan sistemas de coordenadas con límites preestablecidos).
Para todos los espacios de referencia, la coordenada X expresa izquierda y derecha, la Y expresa arriba y abajo, y la Z expresa hacia adelante y hacia atrás. Los valores positivos son hacia la derecha, hacia arriba y hacia atrás, respectivamente.
Las coordenadas que muestra XRFrame.getViewerPose()
dependen del tipo de espacio de referencia solicitado.
Hablaremos más sobre eso cuando lleguemos al bucle de fotogramas. En este momento, debemos seleccionar un tipo de referencia que sea adecuado para la realidad aumentada. Una vez más, se usa mi propiedad de conveniencia.
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);
});
}
Si visitaste la muestra de la sesión de RA envolvente, notarás que, en un principio, la escena es estática y no es una realidad aumentada. Puedes arrastrar y deslizar el dedo para moverte por la escena. Si haces clic en “START AR”, se quitará el fondo y podrás moverte por la escena moviendo el dispositivo. Los modos usan diferentes tipos de espacios de referencia. En el texto destacado anterior, se muestra cómo se selecciona esta opción. Usa los siguientes tipos de referencia:
local
: El origen está en la posición del usuario en el momento de la creación de la sesión. Esto significa que la experiencia no tiene necesariamente un límite inferior bien definido y que la posición exacta del origen puede variar según la plataforma. Aunque no hay límites preestablecidos para el espacio, se espera que el contenido se pueda ver con ningún movimiento además de la rotación. Como puedes ver en nuestro propio ejemplo de RA, es posible que se pueda realizar algún movimiento dentro del espacio.
viewer
: Se usa con mayor frecuencia para el contenido que se presenta intercalado en la página. Este espacio sigue al dispositivo de visualización. Cuando se pasa a getViewerPose, no proporciona ningún seguimiento y, por lo tanto, siempre informa una pose en el origen, a menos que la aplicación la modifique con XRReferenceSpace.getOffsetReferenceSpace()
. El ejemplo usa esto para habilitar el desplazamiento de la cámara basado en el tacto.
Ejecuta un bucle de fotogramas
Conceptualmente, nada cambia con lo que hice en la sesión de RV descrita en mis artículos anteriores. Pasa el tipo de espacio de referencia a XRFrame.getViewerPose()
.
El XRViewerPose
que se muestra será para el tipo de espacio de referencia actual. El uso de viewer
como valor predeterminado permite que una página muestre vistas previas de contenido antes de solicitar el consentimiento del usuario para la RA o la RV. Esto ilustra un punto importante: el contenido intercalado usa el mismo bucle de fotogramas que el contenido envolvente, lo que reduce la cantidad de código que se debe mantener.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(refSpaceType);
if (xrViewerPose) {
// Render based on the pose.
}
}
Conclusión
En esta serie de artículos, solo se abordan los aspectos básicos de la implementación de contenido envolvente en la Web. Las muestras de la API de dispositivos de WebXR de Immersive Web Working Group presentan muchas más funciones y casos de uso. También publicamos un artículo sobre las pruebas de posicionamiento en el que se explica una API para detectar superficies y colocar elementos virtuales en una vista de cámara del mundo real. Consulta el blog de web.dev para ver más artículos en el año que viene.
Foto de David Grandmougin en Unsplash