Tạo phiên thực tế tăng cường sống động bằng WebXR

Trang này sẽ hướng dẫn bạn cách tạo một ứng dụng thực tế tăng cường sống động đơn giản bằng WebXR.

Bạn cần có một môi trường phát triển tương thích với WebXR để bắt đầu.

Tạo trang HTML

WebXR yêu cầu tương tác của người dùng để có thể bắt đầu phiên. Tạo một nút gọi activateXR(). Khi tải trang, người dùng có thể sử dụng nút này để bắt đầu trải nghiệm AR.

Tạo một tệp mới có tên là index.html rồi thêm mã HTML sau vào tệp đó:

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

Khởi tạo third.js

Sẽ không có nhiều điều xảy ra khi bạn nhấn nút Start (Bắt đầu). Để thiết lập môi trường 3D, bạn có thể sử dụng thư viện kết xuất để hiển thị một cảnh.

Trong ví dụ này, bạn sẽ sử dụng three.js, một thư viện kết xuất đồ hoạ 3D JavaScript cung cấp trình kết xuất WebGL. Three.js xử lý hoạt động kết xuất hình ảnh, máy ảnh và biểu đồ cảnh, giúp hiển thị nội dung 3D trên web dễ dàng hơn.

Tạo cảnh

Môi trường 3D thường được mô hình hoá như một cảnh. Tạo một THREE.Scene chứa các phần tử thực tế tăng cường. Mã sau đây cho phép bạn nhìn vào một hộp màu không có ánh sáng trong môi trường thực tế tăng cường.

Thêm mã này vào cuối hàm 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);

Thiết lập tính năng hiển thị bằng third.js

Để có thể xem cảnh này trong môi trường thực tế tăng cường, bạn cần có trình kết xuất hình ảnhmáy ảnh. Trình kết xuất sử dụng WebGL để vẽ cảnh của bạn vào màn hình. Camera mô tả khung nhìn mà cảnh được xem từ đó.

Thêm mã này vào cuối hàm 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;

Tạo XRSession

Điểm truy cập vào WebXR là thông qua XRSystem.requestSession(). Dùng chế độ immersive-ar để cho phép xem nội dung đã kết xuất trong môi trường thực tế.

XRReferenceSpace mô tả hệ toạ độ dùng cho các đối tượng trong thế giới ảo. Chế độ 'local' phù hợp nhất cho trải nghiệm thực tế tăng cường (AR), với không gian tham chiếu có nguồn gốc gần người xem và khả năng theo dõi ổn định.

Để tạo XRSessionXRReferenceSpace, hãy thêm mã này vào cuối hàm 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');

Kết xuất cảnh

Bây giờ, bạn có thể kết xuất cảnh. XRSession.requestAnimationFrame() lên lịch cho một lệnh gọi lại được thực thi khi trình duyệt đã sẵn sàng vẽ một khung.

Trong lệnh gọi lại khung ảnh động, hãy gọi XRFrame.getViewerPose() để lấy tư thế của người xem so với không gian toạ độ cục bộ. Tính năng này dùng để cập nhật máy ảnh trong cảnh, thay đổi cách người dùng nhìn thấy thế giới ảo trước khi trình kết xuất vẽ cảnh bằng máy ảnh đã cập nhật.

Thêm mã này vào cuối hàm 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);

Chạy Hello WebXR

Chuyển đến tệp WebXR trên thiết bị của bạn. Bạn sẽ có thể nhìn thấy một hình khối màu từ mọi mặt.

Thêm thử nghiệm nhấn

Một cách phổ biến để tương tác với thế giới thực tế tăng cường là thông qua kiểm thử lượt truy cập, tìm điểm giao thoa giữa một tia và hình học trong thế giới thực. Trong Hello WebXR, bạn sẽ sử dụng phép kiểm thử lượt truy cập để đặt một bông hoa hướng dương trong thế giới ảo.

Xoá khối minh hoạ

Xoá hình khối không có ánh sáng và thay thế bằng một cảnh có ánh sáng:

const scene = new THREE.Scene();

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

Sử dụng tính năng hit-test

Để khởi chạy chức năng kiểm tra lượt truy cập, hãy yêu cầu phiên bằng tính năng hit-test. Tìm mảnh requestSession() trước đó rồi thêm hit-test vào mảnh đó:

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

Thêm trình tải mô hình

Hiện tại, cảnh quan chỉ chứa một khối màu. Để có trải nghiệm thú vị hơn, hãy thêm trình tải mô hình cho phép tải các mô hình GLTF.

Trong thẻ <head> của tài liệu, hãy thêm ba.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>

Tải các mô hình GLTF

Sử dụng trình tải mô hình ở bước trước để tải kẻ ô nhắm mục tiêu và hoa hướng dương từ web.

Thêm mã này vào phía trên 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) => {

Tạo nguồn thử nghiệm lượt truy cập

Để tính toán giao điểm với các đối tượng thực tế, hãy tạo một XRHitTestSource bằng XRSession.requestHitTestSource(). Tia được sử dụng để thử nghiệm lượt truy cập có không gian tham chiếu viewer làm điểm gốc, có nghĩa là thử nghiệm lượt truy cập được thực hiện từ giữa khung nhìn.

Để tạo nguồn thử nghiệm lượt truy cập, hãy thêm mã này sau khi tạo không gian tham chiếu 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 });

Vẽ kẻ ô nhắm mục tiêu

Để biết rõ vị trí đặt hoa hướng dương, hãy thêm dấu đánh dấu nhắm mục tiêu vào cảnh. Dấu kẻ ô này sẽ gắn vào các bề mặt trong thế giới thực, biểu thị nơi hoa hướng dương sẽ neo vào.

XRFrame.getHitTestResults trả về một mảng XRHitTestResult và hiển thị các giao điểm có hình học thực tế. Sử dụng các giao điểm này để định vị ô nhắm mục tiêu trên mọi khung hình.

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

Thêm lượt tương tác khi nhấn

XRSession nhận được select sự kiện khi người dùng hoàn tất một hành động chính. Trong phiên thực tế tăng cường, hành động này tương ứng với một lần nhấn vào màn hình.

Giúp một hoa hướng dương mới xuất hiện khi người dùng nhấn vào màn hình bằng cách thêm mã sau trong quá trình khởi chạy:

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

Kiểm tra thử nghiệm lượt truy cập

Sử dụng thiết bị di động của bạn để truy cập trang này. Sau khi WebXR xây dựng kiến thức về môi trường, ô vuông sẽ xuất hiện trên bề mặt trong thế giới thực. Nhấn vào màn hình để đặt một bông hoa hướng dương. Bạn có thể xem được từ mọi phía.

Các bước tiếp theo