Cette page vous explique comment créer une application de RA immersive simple à l'aide de WebXR.
Pour commencer, vous aurez besoin d'un environnement de développement compatible avec WebXR.
Créer une page HTML
WebXR nécessite une interaction de l'utilisateur pour pouvoir démarrer une session.
Créez un bouton qui appelle activateXR()
. Une fois la page chargée, l'utilisateur peut utiliser ce bouton pour lancer l'expérience RA.
Créez un fichier nommé index.html
et ajoutez-y le code HTML suivant:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>Hello WebXR!</title>
<!-- three.js -->
<script src="https://unpkg.com/three@0.126.0/build/three.js"></script>
</head>
<body>
<!-- Starting an immersive WebXR session requires user interaction.
We start this one with a simple button. -->
<button onclick="activateXR()">Start Hello WebXR</button>
<script>
async function activateXR() {
// Add a canvas element and initialize a WebGL context that is compatible with WebXR.
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const gl = canvas.getContext("webgl", {xrCompatible: true});
// To be continued in upcoming steps.
}
</script>
</body>
</html>
Initialiser three.js
Peu de choses se passent lorsque vous appuyez sur le bouton "Start" (Démarrer). Pour configurer un environnement 3D, vous pouvez utiliser une bibliothèque de rendu pour afficher une scène.
Dans cet exemple, vous allez utiliser three.js
, une bibliothèque de rendu 3D JavaScript qui fournit un moteur de rendu WebGL. Three.js
gère le rendu, les caméras et les graphes de scène, ce qui facilite l'affichage de contenus 3D sur le Web.
Créer une scène
Un environnement 3D est généralement modélisé sous forme de scène. Créez un THREE.Scene
contenant des éléments RA.
Le code suivant vous permet d'afficher une boîte colorée non éclairée en RA.
Ajoutez ce code en bas de la fonction activateXR()
:
const scene = new THREE.Scene();
// The cube will have a different color on each side.
const materials = [
new THREE.MeshBasicMaterial({color: 0xff0000}),
new THREE.MeshBasicMaterial({color: 0x0000ff}),
new THREE.MeshBasicMaterial({color: 0x00ff00}),
new THREE.MeshBasicMaterial({color: 0xff00ff}),
new THREE.MeshBasicMaterial({color: 0x00ffff}),
new THREE.MeshBasicMaterial({color: 0xffff00})
];
// Create the cube and add it to the demo scene.
const cube = new THREE.Mesh(new THREE.BoxBufferGeometry(0.2, 0.2, 0.2), materials);
cube.position.set(1, 1, 1);
scene.add(cube);
Configurer le rendu à l'aide de Three.js
Pour afficher cette scène en RA, vous avez besoin d'un moteur de rendu et d'une caméra. Le moteur de rendu utilise WebGL pour dessiner votre scène à l'écran. La caméra décrit la fenêtre d'affichage à partir de laquelle la scène est vue.
Ajoutez le code suivant en bas de la fonction activateXR()
:
// Set up the WebGLRenderer, which handles rendering to the session's base layer.
const renderer = new THREE.WebGLRenderer({
alpha: true,
preserveDrawingBuffer: true,
canvas: canvas,
context: gl
});
renderer.autoClear = false;
// The API directly updates the camera matrices.
// Disable matrix auto updates so three.js doesn't attempt
// to handle the matrices independently.
const camera = new THREE.PerspectiveCamera();
camera.matrixAutoUpdate = false;
Créer une XRSession
Le point d'entrée vers WebXR passe par XRSystem.requestSession()
. Utilisez le mode immersive-ar
pour pouvoir visualiser le rendu dans un environnement réel.
Un XRReferenceSpace
décrit le système de coordonnées utilisé pour les objets du monde virtuel.
Le mode 'local'
convient mieux à une expérience de RA, car il offre un suivi stable et un espace de référence initial proche du spectateur.
Pour créer un XRSession
et un XRReferenceSpace
, ajoutez le code suivant en bas de la fonction activateXR()
:
// Initialize a WebXR session using "immersive-ar".
const session = await navigator.xr.requestSession("immersive-ar");
session.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl)
});
// A 'local' reference space has a native origin that is located
// near the viewer's position at the time the session was created.
const referenceSpace = await session.requestReferenceSpace('local');
Rendre la scène
Vous pouvez maintenant effectuer le rendu de la scène. XRSession.requestAnimationFrame()
planifie un rappel qui est exécuté lorsque le navigateur est prêt à dessiner un frame.
Lors du rappel du frame d'animation, appelez XRFrame.getViewerPose()
pour obtenir la position de l'utilisateur par rapport à l'espace de coordonnées local.
Cette méthode permet de mettre à jour la caméra dans la scène, ce qui modifie la façon dont l'utilisateur voit le monde virtuel avant que le moteur de rendu ne dessine la scène à l'aide de la caméra mise à jour.
Ajoutez ce code en bas de la fonction activateXR()
:
// Create a render loop that allows us to draw on the AR view.
const onXRFrame = (time, frame) => {
// Queue up the next draw request.
session.requestAnimationFrame(onXRFrame);
// Bind the graphics framebuffer to the baseLayer's framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER, session.renderState.baseLayer.framebuffer)
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
// In mobile AR, we only have one view.
const view = pose.views[0];
const viewport = session.renderState.baseLayer.getViewport(view);
renderer.setSize(viewport.width, viewport.height)
// Use the view's transform matrix and projection matrix to configure the THREE.camera.
camera.matrix.fromArray(view.transform.matrix)
camera.projectionMatrix.fromArray(view.projectionMatrix);
camera.updateMatrixWorld(true);
// Render the scene with THREE.WebGLRenderer.
renderer.render(scene, camera)
}
}
session.requestAnimationFrame(onXRFrame);
Exécuter Hello WebXR
Accédez au fichier WebXR sur votre appareil. Vous devriez voir un cube de couleur de tous les côtés.
Ajouter un test de positionnement
Une méthode courante d'interaction avec le monde de la RA consiste à utiliser un test de positionnement, qui permet de trouver l'intersection entre un rayon et une géométrie du monde réel. Dans Hello WebXR, vous allez utiliser un test de positionnement pour placer un tournesol dans le monde virtuel.
Retirer le cube de démonstration
Supprimez le cube non éclairé et remplacez-le par une scène qui inclut un éclairage:
const scene = new THREE.Scene();
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);
Utiliser la fonctionnalité hit-test
Pour initialiser la fonctionnalité de test de positionnement, demandez une session avec la fonctionnalité hit-test
. Recherchez le fragment requestSession()
précédent, puis ajoutez-y hit-test
:
const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});
Ajouter un chargeur de modèle
Actuellement, la scène ne contient qu'un cube de couleur. Pour rendre l'expérience plus intéressante, ajoutez un chargeur de modèle, qui permet de charger des modèles glTF.
Dans la balise <head>
de votre document, ajoutez le GLTFLoader
de three.js.
<!-- three.js -->
<script src="https://unpkg.com/three@0.126.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script>
Charger des modèles glTF
Utilisez le chargeur de modèle de l'étape précédente pour charger un réticule de ciblage et un tournesol à partir du Web.
Ajoutez ce code au-dessus de onXRFrame
:
const loader = new THREE.GLTFLoader();
let reticle;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/reticle/reticle.gltf", function(gltf) {
reticle = gltf.scene;
reticle.visible = false;
scene.add(reticle);
})
let flower;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", function(gltf) {
flower = gltf.scene;
});
// Create a render loop that allows us to draw on the AR view.
const onXRFrame = (time, frame) => {
Créer une source de test de coup
Pour calculer les intersections avec des objets réels, créez un XRHitTestSource
à l'aide de XRSession.requestHitTestSource()
.
Le rayon utilisé pour le test de collision a l'espace de référence viewer
comme origine, ce qui signifie que le test de collision est effectué à partir du centre de la fenêtre d'affichage.
Pour créer une source de test de collision, ajoutez le code suivant après avoir créé l'espace de référence local
:
// A 'local' reference space has a native origin that is located
// near the viewer's position at the time the session was created.
const referenceSpace = await session.requestReferenceSpace('local');
// Create another XRReferenceSpace that has the viewer as the origin.
const viewerSpace = await session.requestReferenceSpace('viewer');
// Perform hit testing using the viewer as origin.
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
Dessiner un réticule de ciblage
Pour indiquer clairement où le tournesol sera placé, ajoutez un réticule de ciblage à la scène. Ce réticule semblera coller aux surfaces réelles, indiquant l'emplacement où le tournesol sera ancré.
XRFrame.getHitTestResults
renvoie un tableau de XRHitTestResult
et expose les intersections avec la géométrie réelle.
Utilisez ces intersections pour positionner le réticule de ciblage sur chaque frame.
camera.projectionMatrix.fromArray(view.projectionMatrix);
camera.updateMatrixWorld(true);
const hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length > 0 && reticle) {
const hitPose = hitTestResults[0].getPose(referenceSpace);
reticle.visible = true;
reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
reticle.updateMatrixWorld(true);
}
Ajouter des interactions à l'appui
XRSession
reçoit des événements select
lorsque l'utilisateur effectue une action principale.
Dans une session de RA, cela correspond à un appui sur l'écran.
Pour qu'un nouveau tournesol apparaisse lorsque l'utilisateur appuie sur l'écran, ajoutez ce code lors de l'initialisation:
let flower;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", function(gltf) {
flower = gltf.scene;
});
session.addEventListener("select", (event) => {
if (flower) {
const clone = flower.clone();
clone.position.copy(reticle.position);
scene.add(clone);
}
});
Tester le test de positionnement
Accédez à la page avec votre appareil mobile. Une fois que WebXR a compris l'environnement, le réticule doit apparaître sur les surfaces du monde réel. Appuyez sur l'écran pour placer un tournesol, qui peut être vu de tous les côtés.
Étapes suivantes
- Consultez la spécification d'API WebXR Device.
- Consultez la documentation de référence WebXR sur MDN Web Docs.
- Essayez les exemples WebXR.
- Créez une application de réalité augmentée à l'aide de l'API WebXR Device (atelier de programmation).