Tutorial AR Universal: Realidad Aumentada sin WebXR

un modelo 3D en formato glb de un lobo para realidad aumentada
Realidad Aumentada sin WebXR

El problema de la realidad aumentada en la Web

Uno de los mayores desafíos al desarrollar Realidad Aumentada (AR) para la web es la compatibilidad. Mientras que Android soporta WebXR nativamente en Chrome, los dispositivos iOS (iPhone/iPad) a menudo requieren visores específicos o aplicaciones externas para funcionar correctamente.

Si has intentado crear una experiencia webAR, probablemente te has topado con este muro: WebXR, el estándar actual, funciona de maravilla en Android (Chrome), pero el soporte en iOS (Safari) sigue siendo limitado o requiere visores externos.

Esto deja a los desarrolladores con dos opciones: pagar licencias costosas de plataformas propietarias o crear aplicaciones nativas. Pero hoy vamos a tomar una tercera vía: AR Universal.

Hoy vamos a solucionar esto creando un sistema de AR Universal. Utilizaremos A-Frame para los gráficos 3D y HTML5 nativo para acceder a la cámara, logrando un efecto de realidad aumentada que funciona en prácticamente cualquier navegador moderno, sin necesidad de instalaciones.

En este tutorial, construiremos un sistema que utiliza A-Frame para los gráficos y HTML5 puro para la cámara, logrando un efecto que funciona en el 99% de los dispositivos móviles modernos sin instalar nada.

¿Cómo funciona (La Lógica Técnica)?

Para lograr esto sin usar las APIs complejas de WebXR, utilizamos una técnica de capas superpuestas:

  • La Capa de Realidad (Video): Usamos la etiqueta <video> de HTML5 para capturar el feed de la cámara trasera. Esto actúa como nuestro «fondo».
  • La Capa Virtual (Canvas Transparente): Colocamos una escena de A-Frame (<a-scene>) con fondo transparente exactamente encima del video.
  • La Magia de los Sensores (IMU): Aquí está la clave. En lugar de detectar superficies (que requiere mucha potencia de procesamiento), utilizamos los sensores de orientación del móvil (giroscopio y acelerómetro). Cuando giras tu teléfono a la izquierda, la cámara virtual gira a la izquierda, creando la ilusión de que el objeto 3D está fijo en el espacio.

Importante: 3DoF vs 6DoF

Es crucial entender que esta es una experiencia 3DoF (3 Degrees of Freedom).

Lo que SÍ hace: Puedes girar sobre tu propio eje y mirar alrededor; el objeto se quedará en su sitio.

Lo que NO hace: Si caminas hacia adelante o hacia atrás, el objeto se moverá contigo (no se hace más grande o pequeño automáticamente al acercarte), ya que no estamos rastreando tu posición en el espacio, solo tu rotación.

Prerrequisitos antes de empezar la app de realidad aumentada

Para que este código funcione en tu móvil, necesitas cumplir dos requisitos fundamentales:

  • Servidor Seguro (HTTPS): Los navegadores modernos bloquean el acceso a la cámara si el sitio no es seguro.
  • En local: Usa soluciones como ngrok o la extensión «Live Server» de VS Code configurada para móviles.
  • En producción: Sube tu código a GitHub Pages, Vercel o Netlify (que te dan HTTPS gratis).
  • Modelo 3D (.glb): Necesitas un archivo 3D. En el código usamos wolf.glb, pero puedes descargar cualquier modelo gratuito en formato .glb o .gltf (asegúrate de que sea liviano, menos de 5MB para web).

Ahora si pasemos al codigo de la App.

En este primer ejemplo, crearemos una experiencia simple de «Tocar para colocar». Al hacer clic en la pantalla, el modelo 3D aparecerá frente a ti.

Realidad Aumentada sin WebXR - Version Basica
Realidad Aumentada sin WebXR – Version Basica

Características:

  • Detección automática de iOS para pedir permisos de sensores.
  • Uso de cámara trasera (facingMode: environment).
  • Colocación de objetos basada en la dirección de la mirada.
  • Aquí tienes el script completo para copiar y probar.

Puedes hacer tus marcadores de realidad aumentada con la herramienta de Realidad Aumentada Empezando Desde Cero: Compilador de Marcadores AR | Crea Realidad Aumentada Gratis

Este es el script completo de la aplicación para que puedas probarla y disfrutarla.

<script>
const videoElement = document.getElementById('cam-feed');
const startBtn = document.getElementById('start-btn');
const msg = document.getElementById('msg');
const scene = document.querySelector('a-scene');
const camera = document.getElementById('camera');

const ESCALA_MODELO = '4 4 4';
const ROTACION_MODELO = '0 -90 0';

const isIOS = typeof DeviceOrientationEvent !== 'undefined' && typeof DeviceOrientationEvent.requestPermission === 'function';

async function startExperience() {
startBtn.style.display = 'none';
msg.innerText = "Accediendo a cámara...";

if (isIOS) {
try {
const permission = await DeviceOrientationEvent.requestPermission();
if (permission !== 'granted') {
alert("Necesitamos acceso al giroscopio para mover la cámara.");
return;
}
} catch (e) {
console.error(e);
}
}

try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: "environment"
},
audio: false
});
videoElement.srcObject = stream;
msg.innerText = "¡Toca la pantalla para poner al modelo!";
} catch (err) {
console.error("Error de cámara:", err);
msg.innerText = "Error: No pudimos acceder a la cámara. Asegúrate de usar HTTPS.";
msg.style.backgroundColor = "red";
}
}
startBtn.style.display = 'inline-block';
msg.style.display = 'none';

startBtn.addEventListener('click', startExperience);

document.addEventListener('click', (e) => {

if(e.target === startBtn) return;

if (!videoElement.srcObject) return;

const entity = document.createElement('a-entity');
entity.setAttribute('gltf-model', '#model-asset');

entity.setAttribute('scale', ESCALA_MODELO);
entity.setAttribute('rotation', ROTACION_MODELO);

const cameraObj = camera.object3D;
const direction = new THREE.Vector3();
cameraObj.getWorldDirection(direction);

direction.multiplyScalar(-2);

const pos = new THREE.Vector3();
pos.copy(cameraObj.position).add(direction);

pos.y = cameraObj.position.y - 1.5;

entity.object3D.position.copy(pos);

entity.object3D.lookAt(cameraObj.position);
entity.object3D.rotation.x = 0;
entity.object3D.rotation.z = 0;

scene.appendChild(entity);

msg.innerText = "¡Modelo colocado! Toca para otro.";
});
</script>

Ahora pasemos a algo más interesante en realidad aumentada.

Versión Avanzada (Exclusivo Patreon)

Realidad Aumentada sin WebXR - Version Avanzada
Realidad Aumentada sin WebXR – Version Avanzada

Si quieres llevar esta experiencia al siguiente nivel, he preparado una versión mejorada exclusiva para mis patreones.

¿Qué mejoras incluye el código PRO?

  • Modo Fantasma (Ghost Mode): Ves una previsualización transparente del modelo flotando frente a ti antes de colocarlo.
  • Sistema de Anclaje: Un botón dedicado para «Fijar» el modelo en el mundo real, separándolo del movimiento de la cámara.
  • UI/UX Mejorada: Botones profesionales, mira central (crosshair) y feedback visual de estado.
  • Animación de espera: El modelo «fantasma» flota suavemente mientras buscas el lugar perfecto.
  • Esta versión elimina la frustración de colocar objetos a ciegas y ofrece una experiencia mucho más cercana a una app nativa.
  • Ambas versiones de código comentado (Versión Básica y Versión Avanzada) línea por línea para mejorar tu aprendizaje.

Da clic en la imagen para continuar con el post exclusivo.

logo de realidad aumentada empezando desde cero y patreon
Realidad Aumentada Empezando Desde Cero y Patreon

Con estas técnicas, has logrado saltar la barrera de entrada de la Realidad Aumentada. Ya no dependes de que Apple o Google se pongan de acuerdo en un estándar; tienes una solución que funciona hoy, en el navegador que tus usuarios ya tienen instalado.

Recuerda que, aunque esta solución es robusta para visualización de productos y marketing, no reemplaza a WebXR para interacciones físicas complejas (como detectar el suelo o paredes). Sin embargo, para la mayoría de los casos de uso creativo, ¡es más que suficiente!

Si te ha sido útil este código, considera suscribirte al Patreon para acceder a más templates de Realidad Aumentada avanzada.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Scroll al inicio
0
Would love your thoughts, please comment.x
()
x