Utwórz wciągającą sesję AR za pomocą WebXR

Na tej stronie znajdziesz instrukcje tworzenia prostej aplikacji AR za pomocą WebXR.

Aby rozpocząć, musisz mieć środowisko programistyczne zgodne z WebXR.

Utwórz stronę HTML

WebXR wymaga interakcji użytkownika, aby można było rozpocząć sesję. Utwórz przycisk, który wywołuje funkcję activateXR(). Po załadowaniu strony użytkownik może użyć tego przycisku, aby rozpocząć korzystanie z rzeczywistości rozszerzonej.

Utwórz nowy plik o nazwie index.html i dodaj do niego ten kod HTML:

<!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>

Inicjowanie three.js

Po naciśnięciu przycisku Start nic się nie dzieje. Aby skonfigurować środowisko 3D, możesz użyć biblioteki renderowania do wyświetlenia sceny.

W tym przykładzie użyjesz biblioteki JavaScript do renderowania 3D three.js, która udostępnia moduł renderowania WebGL. Three.js obsługuje renderowanie, kamery i grafy sceny, co ułatwia wyświetlanie treści 3D w internecie.

Tworzenie sceny

Środowisko 3D jest zwykle modelowane jako scena. Utwórz THREE.Scene zawierający elementy AR. Poniższy kod umożliwia wyświetlenie nieoświetlonego kolorowego pudełka w AR.

Dodaj ten kod na dole funkcji 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);

Konfigurowanie renderowania za pomocą three.js

Aby wyświetlić tę scenę w AR, potrzebujesz renderowaniakamery. Mechanizm renderowania wyświetla scenę na ekranie za pomocą WebGL. Kamera określa obszar wyświetlania, z którego widoczna jest scena.

Dodaj ten kod na dole funkcji 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;

Tworzenie sesji XR

Punkt wejścia do WebXR to XRSystem.requestSession(). Użyj trybu immersive-ar, aby wyświetlić wyrenderowane treści w środowisku rzeczywistym.

Element XRReferenceSpaceopisuje układ współrzędnych używany dla obiektów w świecie wirtualnym. Tryb 'local' najlepiej sprawdza się w przypadku AR, w którym przestrzeń referencyjna ma początek w pobliżu widza i jest stabilne podczas śledzenia.

Aby utworzyć XRSession i XRReferenceSpace, dodaj ten kod na końcu funkcji 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');

Renderowanie sceny

Teraz możesz wyrenderować scenę. XRSession.requestAnimationFrame() planuje wywołanie zwrotne, które jest wykonywane, gdy przeglądarka będzie gotowa do narysowania klatki.

Podczas wywołania zwrotnego ramki animacji wywołaj funkcję XRFrame.getViewerPose(), aby uzyskać pozę widza w stosunku do lokalnej przestrzeni współrzędnych. Służy on do aktualizowania kamery w scenie, zmieniając sposób, w jaki użytkownik widzi świat wirtualny, zanim renderer narysuje scenę za pomocą zaktualizowanej kamery.

Dodaj ten kod na dole funkcji 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);

Uruchamianie Hello WebXR

Przejdź do pliku WebXR na urządzeniu. Kolorowy sześcian powinien być widoczny ze wszystkich stron.

Dodawanie testu skuteczności

Typowym sposobem na interakcję ze światem AR jest test kolizji, który znajduje przecięcie promienia z rzeczywistą geometrią. W Hello WebXR do umieszczenia słoneczników w świecie wirtualnym użyjesz testu kolizji.

Usuń kostkę demonstracyjną

Usuń kostkę z nieotwartą pokrywą i zastąp ją sceną z oświetleniem:

const scene = new THREE.Scene();

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);

Korzystanie z funkcji hit-test

Aby zainicjować funkcję testu trafień, poproś o sesję z funkcją hit-test. Znajdź poprzedni fragment requestSession() i dodaj do niego fragment hit-test:

const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});

Dodawanie programu ładującego model

Obecnie scena zawiera tylko kolorowy sześcian. Aby korzystanie z aplikacji było ciekawsze, dodaj moduł wczytujący modele, który umożliwia ładowanie modeli GLTF.

W tagu <head> dokumentu dodaj three.jsGLTFLoader.

<!-- 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>

Wczytywanie modeli GLTF

Użyj narzędzia do wczytywania modeli z poprzedniego etapu, aby załadować z sieci siatkę celowniczą i słonecznik.

Dodaj ten kod nad wierszem 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) => {

Tworzenie źródła testu dopasowania

Aby obliczyć przecięcia z rzeczywistymi obiektami, utwórz XRHitTestSource za pomocą XRSession.requestHitTestSource(). Promień używany do testowania trafień ma punkt odniesienia viewer, co oznacza, że test trafień jest przeprowadzany na środku widocznego obszaru.

Aby utworzyć źródło testu działań, dodaj ten kod po utworzeniu przestrzeni referencyjnej 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 });

Rysowanie siatki kierunkowej

Aby było jasne, gdzie ma się znaleźć słoneczniczek, dodaj do sceny celownik. Ta siatka będzie przylegać do rzeczywistych powierzchni, co będzie oznaczać, gdzie ma być przymocowany kwiat.

XRFrame.getHitTestResults zwraca tablicę XRHitTestResult i wyświetla przecięcia z geometryką rzeczywistą. Użyj tych przekrojów, aby umieścić siatkę kierowania w każdej ramce.

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);
}

Dodawanie interakcji po kliknięciu

XRSession otrzymuje zdarzenia select, gdy użytkownik wykona działanie główne. W sesji AR odpowiada to kliknięciu ekranu.

Aby nowa słonecznia pojawiała się, gdy użytkownik kliknie ekran, dodaj ten kod podczas inicjalizacji:

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);
  }
});

Testowanie testu trafień

Przejdź do strony na urządzeniu mobilnym. Gdy WebXR zrozumie warunki otoczenia, celownik powinien pojawić się na powierzchniach w świecie rzeczywistym. Kliknij ekran, aby umieścić słoneczniki, które można oglądać ze wszystkich stron.

Dalsze kroki