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

Na tej stronie dowiesz się, jak utworzyć prostą i wciągającą aplikację AR za pomocą WebXR.

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

Utwórz stronę HTML

WebXR wymaga interakcji użytkownika, aby móc rozpocząć sesję. Utwórz przycisk wywołujący nazwę activateXR(). Po wczytaniu strony użytkownik może za pomocą tego przycisku uruchomić tryb AR.

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>

Zainicjuj Trzy.js

Po naciśnięciu przycisku Start niewiele się wydarzy. Aby skonfigurować środowisko 3D, możesz wyświetlić scenę za pomocą biblioteki renderowania.

W tym przykładzie użyjesz three.js – biblioteki JavaScriptu 3D z mechanizmem renderowania WebGL. Three.js obsługuje renderowanie, aparaty i wykresy scen, co ułatwia wyświetlanie treści 3D w internecie.

Tworzenie sceny

Środowisko 3D jest zazwyczaj modelowane jako scena. Utwórz obiekt THREE.Scene zawierający elementy AR. Poniższy kod pozwala zobaczyć niepodświetlone kolorowe pole 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ą plikuthree.js

Aby wyświetlić tę scenę w AR, potrzebujesz renderera i aparatu. Renderowanie wykorzystuje WebGL do rysowania sceny na ekranie. Kamera opisuje widoczny obszar, z którego widać scenę.

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 jest prowadzony przez XRSystem.requestSession(). Użyj trybu immersive-ar, aby umożliwić wyświetlanie wyrenderowanych treści w rzeczywistym środowisku.

XRReferenceSpace opisuje układ współrzędnych używany w obiektach w świecie wirtualnym. Tryb 'local' najlepiej sprawdza się w rzeczywistości rozszerzonej z przestrzenią referencyjną, której punkt początkowy znajduje się w pobliżu gogli, i stabilnym śledzeniem.

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

Renderuj scenę

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

Podczas wywołania zwrotnego ramki animacji wywołaj XRFrame.getViewerPose(), aby uzyskać położenie widza w odniesieniu do lokalnej przestrzeni współrzędnych. Używa się ich do aktualizowania kamery nagrywanej w scenie, co pozwala zmienić sposób, w jaki użytkownik widzi wirtualny świat, zanim mechanizm renderowania zacznie renderować scenę przy użyciu 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);

Uruchom Hello WebXR

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

Dodaj test działania

Typowym sposobem interakcji ze światem AR jest test trafień, w którym znajduje się przecięcie promienia z geometrią świata rzeczywistego. W grze Hello WebXR przeprowadzisz test, aby umieścić słonecznik w wirtualnym świecie.

Usuń kostkę demonstracyjną

Usuń nieoświetloną kostkę 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);

Używaj funkcji hit-test

Aby zainicjować funkcję testu działania, wyślij żądanie sesji za pomocą funkcji hit-test. Znajdź poprzedni fragment requestSession() i dodaj do niego element hit-test:

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

Dodaj moduł ładowania modeli

Obecnie scena zawiera tylko kolorowy sześcian. Aby korzystanie z aplikacji było bardziej interesujące, dodaj moduł ładowania modeli, który umożliwia ładowanie modeli GLTF.

W tagu <head> dokumentu dodaj ciąg three.js' GLTFLoader.

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

Wczytaj modele GLTF

Aby wczytać siatkę kierowania i słonecznik z internetu, użyj narzędzia ładującego model z poprzedniego kroku.

Dodaj ten kod powyżej 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 działania

Aby obliczyć przecięcia z obiektami rzeczywistymi, utwórz XRHitTestSource w XRSession.requestHitTestSource(). Promień używany do testowania trafień ma przestrzeń referencyjną viewer jako punkt początkowy, co oznacza, że test działania odbywa się na środku widocznego obszaru.

Aby utworzyć źródło testu działania, 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 kierowania

Aby jasno wskazać, gdzie zostanie umieszczony słonecznik, dodaj do sceny siatkę kierowania. Ta siatka będzie przyklejona do rzeczywistej powierzchni, wskazując, gdzie zostanie zakotwiczony słonecznik.

XRFrame.getHitTestResults zwraca tablicę XRHitTestResult i ujawnia skrzyżowania z rzeczywistą geometrią. Użyj tych przekrojów, aby ustawić siatkę kierowania w każdej klatce.

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.

Dopilnuj, aby nowy słonecznik pojawił się po dotknięciu ekranu przez użytkownika, dodając ten kod podczas inicjowania:

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 testów trafień

Użyj urządzenia mobilnego, aby otworzyć tę stronę. Gdy WebXR zrozumie środowisko, siatka siatki powinna pojawić się na rzeczywistych powierzchniach. Dotknij ekranu, aby umieścić słonecznik. Jest on widoczny ze wszystkich stron.

Dalsze kroki