Mem-build aplikasi augmented reality (AR) menggunakan WebXR Device API

1. Sebelum memulai

Codelab ini membahas contoh proses build aplikasi web AR. Contoh ini menggunakan JavaScript untuk merender model 3D yang muncul seolah-olah ada di dunia nyata.

Anda menggunakan WebXR Device API yang menggabungkan fungsi AR dan virtual reality (VR). Anda berfokus pada ekstensi AR ke WebXR Device API untuk membuat aplikasi AR sederhana yang berjalan di web interaktif.

Apa yang dimaksud dengan AR?

AR adalah istilah yang biasanya digunakan untuk menjelaskan gabungan grafis yang dihasilkan komputer dengan dunia nyata. Untuk AR berbasis ponsel, ini berarti menempatkan grafis komputer melalui feed kamera langsung dengan meyakinkan. Agar efek ini tetap realistis saat ponsel bergerak di dunia nyata, perangkat berkemampuan AR perlu memahami lingkungan nyata yang dilaluinya serta dapat menentukan posenya (posisi dan orientasi) dalam ruang 3D. Hal ini dapat mencakup pendeteksian permukaan dan memperkirakan pencahayaan lingkungan.

AR telah digunakan secara luas dalam aplikasi setelah rilis ARCore Google dan ARKit Apple, baik untuk filter selfie maupun game berbasis AR.

Yang akan Anda build

Dalam codelab ini, Anda akan membuat aplikasi web yang menempatkan model di dunia nyata menggunakan augmented reality. Aplikasi Anda akan:

  1. Menggunakan sensor perangkat target untuk menentukan dan melacak posisi serta orientasinya di dunia nyata
  2. Merender model 3D yang digabungkan di bagian atas tampilan kamera langsung
  3. Menjalankan hit test untuk menempatkan objek di atas permukaan yang ditemukan di dunia nyata

Yang akan Anda pelajari

  • Cara menggunakan WebXR Device API
  • Cara mengonfigurasi scene AR dasar
  • Cara menemukan permukaan menggunakan hit test AR
  • Cara memuat dan merender model 3D yang disinkronkan dengan feed kamera dunia nyata
  • Cara merender bayangan berdasarkan model 3D

Codelab ini berfokus pada AR API. Konsep dan blok kode yang tidak-relevan akan dipoles dan disediakan untuk Anda dalam kode repositori yang sesuai.

Yang Anda butuhkan

Klik Coba di perangkat AR Anda untuk mencoba langkah pertama codelab ini. Jika Anda mendapatkan halaman dengan pesan "Browser Anda tidak memiliki fitur AR", pastikan Layanan Google Play untuk AR telah terinstal di perangkat Android Anda.

2. Menyiapkan lingkungan pengembangan

Download kodenya

  1. Klik link berikut guna mendownload semua kode untuk codelab ini di workstation Anda:

  1. Mengekstrak file zip yang didownload. Tindakan ini akan mengekstrak folder root (ar-with-webxr-master), yang berisi direktori yang menyediakan beberapa langkah codelab ini, beserta semua materi yang diperlukan.

Folder step-03 dan step-04 berisi status akhir yang diinginkan dari langkah ketiga dan keempat codelab ini, serta hasil final. Folder tersebut disediakan sebagai referensi

Anda melakukan semua pekerjaan coding di direktori work.

Menginstal server web

  1. Anda bebas untuk menggunakan server web Anda sendiri. Jika Anda belum menyiapkannya, bagian ini akan menjelaskan cara menyiapkan Server Web untuk Chrome.
    Jika aplikasi tersebut belum diinstal di workstation, Anda dapat menginstalnya dari Chrome Web Store.

  1. Setelah menginstal aplikasi Server Web untuk Chrome, buka chrome://apps, lalu klik ikon Server Web:

Ikon Server Web

Anda akan melihat dialog ini berikutnya, yang memungkinkan Anda mengonfigurasi server web lokal:

Mengonfigurasi Server Web Chrome

  1. Klik pilih folder, lalu pilih folder ar-with-webxr-master. Tindakan ini memungkinkan Anda menyalurkan pekerjaan yang sedang berlangsung melalui URL yang ditandai dalam dialog server web (di bagian URL Server Web).
  2. Di bagian Opsi (perlu dimulai ulang), pilih kotak centang Tampilkan index.html secara otomatis..
  3. Alihkan tombol Server web ke Hentikan, lalu alihkan kembali ke Dimulai.Memulai ulang Server Web Chrome
  4. Verifikasi bahwa setidaknya satu URL Server Web muncul: http://127.0.0.1:8887—URL localhost default.

Menyiapkan penerusan port

Konfigurasikan perangkat AR sehingga server web dapat mengakses port yang sama di workstation Anda saat mengunjungi localhost:8887.

  1. Di workstation pengembangan Anda, buka chrome://inspect, lalu klik Penerusan port...: chrome://inspect
  2. Gunakan dialog Setelan penerusan port untuk meneruskan port 8887 ke localhost:8887.
  3. Pilih kotak centang Aktifkan penerusan port:

Mengonfigurasi penerusan port

Memverifikasi penyiapan Anda

Uji koneksi Anda:

  1. Hubungkan perangkat AR ke workstation dengan kabel USB.
  2. Pada perangkat AR di Chrome, masukkan http://localhost:8887 di kolom URL. Perangkat AR Anda harus meneruskan permintaan ini ke server web workstation pengembangan. Anda akan melihat direktori file.
  3. Di perangkat AR, klik step-03 untuk memuat file step-03/index.html di browser Anda.

Anda akan melihat halaman yang berisi tombol Mulai augmented reality

Namun, jika Anda melihat halaman error Browser tidak didukung, artinya perangkat Anda mungkin tidak kompatibel.

ARCore didukung

ARCore tidak didukung

Koneksi ke server web Anda kini akan berfungsi dengan perangkat AR.

  1. Klik Mulai augmented reality. Anda mungkin akan diminta untuk menginstal ARCore.

Menginstal perintah ARCore

Anda akan melihat permintaan izin kamera saat pertama kali menjalankan aplikasi AR.

Chrome meminta izin kameraDialog izin

Setelah semuanya siap, Anda akan melihat scene kubus yang ditempatkan di atas feed kamera. Pemahaman scene meningkat saat lebih banyak bagian dunia nyata diurai oleh kamera, sehingga menggerakkannya dapat membantu menstabilkan berbagai hal.

3 Mengonfigurasi WebXR

Pada langkah ini, Anda akan mempelajari cara menyiapkan sesi WebXR dan scene AR dasar. Halaman HTML disediakan dengan gaya CSS dan JavaScript untuk mengaktifkan fungsi AR dasar. Hal ini mempercepat proses penyiapan, sehingga memungkinkan codelab berfokus pada fitur AR.

Halaman HTML

Anda mem-build pengalaman AR ke dalam halaman web tradisional menggunakan teknologi web yang sudah ada. Dalam pengalaman ini, Anda menggunakan kanvas yang merender layar penuh, sehingga file HTML tidak perlu harus terlalu rumit.

Fitur AR memerlukan gestur pengguna untuk memulai, sehingga ada beberapa komponen Desain Material untuk menampilkan tombol Mulai AR dan pesan browser yang tidak didukung.

File index.html yang sudah ada dalam direktori work Anda akan terlihat seperti berikut. Ini adalah subkumpulan konten yang sebenarnya; jangan menyalin kode ini ke file Anda.

<!-- Don't copy this code into your file! -->
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Building an augmented reality application with the WebXR Device API</title>
    <link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>

    <!-- three.js -->
    <script src="https://unpkg.com/three@0.123.0/build/three.js"></script>
    <script src="https://unpkg.com/three@0.123.0/examples/js/loaders/GLTFLoader.js"></script>

    <script src="../shared/utils.js"></script>
    <script src="app.js"></script>
  </head>
  <body>
  <!-- Information about AR removed for brevity. -->

  <!-- Starting an immersive WebXR session requires user interaction. Start the WebXR experience with a simple button. -->
  <a onclick="activateXR()" class="mdc-button mdc-button--raised mdc-button--accent">
    Start augmented reality
  </a>

</body>
</html>

Membuka kode JavaScript kunci

Titik awal untuk aplikasi Anda adalah app.js. File ini menyediakan beberapa boilerplate untuk menyiapkan pengalaman AR.

Direktori kerja Anda juga sudah menyertakan kode aplikasi (app.js).

Memeriksa dukungan WebXR dan AR

Sebelum pengguna dapat menggunakan AR, periksa keberadaan navigator.xr dan fitur XR yang diperlukan. Objek navigator.xr adalah titik entri untuk WebXR Device API, sehingga objek ini harus ada jika perangkat ternyata kompatibel. Pastikan juga apakah mode sesi "immersive-ar" didukung.

Jika semuanya berfungsi dengan baik, mengklik tombol Masuk augmented reality akan membuat sesi XR. Jika tidak, onNoXRDevice() akan dipanggil (dalam shared/utils.js) yang akan menampilkan pesan yang menunjukkan kurangnya dukungan AR.

Kode ini sudah ada di app.js, sehingga Anda tidak perlu melakukan perubahan.

(async function() {
  if (navigator.xr && await navigator.xr.isSessionSupported("immersive-ar")) {
    document.getElementById("enter-ar").addEventListener("click", activateXR)
  } else {
    onNoXRDevice();
  }
})();

Meminta XRSession

Saat Anda mengklik Masuk augmented reality, kode akan memanggil activateXR(). Tindakan ini akan memulai pengalaman AR.

  1. Temukan fungsi activateXR() di app.js. Beberapa kode telah diabaikan:
activateXR = async () => {
  // Initialize a WebXR session using "immersive-ar".
  this.xrSession = /* TODO */;

  // Omitted for brevity
}

Titik entri ke WebXR adalah melalui XRSystem.requestSession(). Gunakan mode immersive-ar agar konten yang dirender dapat dilihat di lingkungan dunia nyata.

  1. Melakukan inisialisasi this.xrSession menggunakan mode "immersive-ar":
activateXR = async () => {
  // Initialize a WebXR session using "immersive-ar".
  this.xrSession = await navigator.xr.requestSession("immersive-ar");

  // ...
}

Melakukan inisialisasi XRReferenceSpace

XRReferenceSpace menjelaskan sistem koordinat yang digunakan untuk objek yang ada dalam dunia virtual. Mode 'local' sangat cocok digunakan untuk pengalaman AR, dengan ruang referensi yang memiliki asal di dekat penampil dan pelacakan yang stabil.

Melakukan inisialisasi this.localReferenceSpace di onSessionStarted() dengan kode berikut:

this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");

Menentukan loop animasi

  1. Gunakan requestAnimationFrame XRSession untuk memulai loop rendering, yang mirip dengan window.requestAnimationFrame.

Pada setiap frame, onXRFrame dipanggil dengan stempel waktu dan XRFrame.

  1. Selesaikan penerapan onXRFrame. Saat frame digambar, lakukan antrean di permintaan berikutnya dengan menambahkan:
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
  1. Tambahkan kode untuk menyiapkan lingkungan grafis. Tambahkan ke bagian bawah onXRFrame:
// Bind the graphics framebuffer to the baseLayer's framebuffer.
const framebuffer = this.xrSession.renderState.baseLayer.framebuffer;
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
this.renderer.setFramebuffer(framebuffer);
  1. Untuk menentukan pose penampil, gunakan XRFrame.getViewerPose(). XRViewerPose ini menjelaskan posisi dan orientasi perangkat di ruang. Ini juga berisi array XRView, yang menjelaskan setiap sudut pandang yang menjadi tempat untuk merender scene, agar dapat ditampilkan dengan benar di perangkat saat ini. Meskipun VR stereoskopis memiliki dua tampilan (satu untuk setiap mata), perangkat AR hanya memiliki satu tampilan.
    Informasi dalam pose.views paling sering digunakan untuk mengonfigurasi matriks tampilan dan matriks proyeksi kamera virtual. Informasi ini memengaruhi cara scene ditata dalam 3D. Saat kamera dikonfigurasi, scene dapat dirender.
  2. Tambahkan ke bagian bawah onXRFrame:
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(this.localReferenceSpace);
if (pose) {
  // In mobile AR, we only have one view.
  const view = pose.views[0];

  const viewport = this.xrSession.renderState.baseLayer.getViewport(view);
  this.renderer.setSize(viewport.width, viewport.height);

  // Use the view's transform matrix and projection matrix to configure the THREE.camera.
  this.camera.matrix.fromArray(view.transform.matrix);
  this.camera.projectionMatrix.fromArray(view.projectionMatrix);
  this.camera.updateMatrixWorld(true);

  // Render the scene with THREE.WebGLRenderer.
  this.renderer.render(this.scene, this.camera);
}

Melakukan pengujian

Jalankan aplikasi; di perangkat pengembangan Anda, buka work/index.html. Anda akan melihat feed kamera dengan kubus yang mengambang di ruang tempat perspektifnya dapat berubah saat Anda menggerakkan perangkat. Pelacakan akan meningkat semakin Anda bergerak, jadi jelajahi apa yang sesuai untuk Anda dan perangkat Anda.

Jika Anda mengalami masalah saat menjalankan aplikasi, lihat bagian Pengantar dan Menyiapkan lingkungan pengembangan.

4. Menambahkan reticle penargetan

Setelah penyiapan scene AR dasar selesai, kini saatnya untuk mulai berinteraksi dengan dunia nyata menggunakan hit test. Di bagian ini, Anda akan memprogram hit test dan menggunakannya untuk menemukan permukaan di dunia nyata.

Memahami hit test

Hit test umumnya merupakan cara untuk membuang garis lurus dari sebuah titik di ruang ke beberapa arah dan menentukan apakah garis tersebut bersimpangan dengan objek yang diinginkan. Dalam contoh ini, Anda mengarahkan perangkat ke lokasi di dunia nyata. Bayangkan sebuah sinar berjalan dari kamera perangkat dan langsung memasuki dunia fisik di depannya.

WebXR Device API memungkinkan Anda mengetahui apakah sinar ini bersimpangan dengan objek di dunia nyata, yang ditentukan oleh kemampuan AR dan pemahamannya terhadap dunia nyata.

Penjelasan hit test

Meminta XRSession dengan fitur tambahan

Untuk melakukan hit test, fitur tambahan diperlukan saat meminta XRSession.

  1. Di app.js, temukan navigator.xr.requestSession.
  2. Tambahkan fitur "hit-test" dan "dom-overlay" sebagai requiredFeature seperti berikut:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
  requiredFeatures: ["hit-test", "dom-overlay"]
});
  1. Konfigurasikan overlay DOM. Tambahkan lapisan elemen document.body ke tampilan kamera AR, seperti:
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
  requiredFeatures: ["hit-test", "dom-overlay"],
  domOverlay: { root: document.body }
});

Menambahkan perintah gerakan

ARCore berfungsi sangat baik saat pemahaman yang memadai tentang lingkungan telah dibangun. Hal ini dilakukan melalui proses yang disebut pelokalan dan pemetaan simultan (SLAM), yang menggunakan poin fitur yang berbeda secara visual untuk menghitung perubahan lokasi dan karakteristik lingkungan.

Gunakan "dom-overlay" dari langkah sebelumnya untuk menampilkan perintah gerakan di atas feed kamera.

Tambahkan <div> ke index.html dengan ID stabilization. <div> ini menampilkan animasi kepada pengguna yang mewakili status stabilisasi dan meminta mereka untuk bergerak di antara perangkat untuk meningkatkan proses SLAM. Animasi ini ditampilkan setelah pengguna berada dalam AR dan akan disembunyikan setelah reticle menemukan permukaan, yang dikontrol oleh class <body>.

  <div id="stabilization"></div>

</body>
</html>

Menambahkan reticle

Gunakan reticle untuk menunjukkan lokasi yang dituju oleh tampilan perangkat.

  1. Di app.js, ganti panggilan DemoUtils.createCubeScene() di setupThreeJs() dengan Three.Scene() yang kosong.
setupThreeJs() {
  // ...

  // this.scene = DemoUtils.createCubeScene();
  this.scene = DemoUtils.createLitScene();
}
  1. Isi scene baru dengan objek yang mewakili titik persimpangan. Class Reticle yang disediakan menangani pemuatan model reticle di shared/utils.js.
  2. Tambahkan Reticle ke scene di setupThreeJs():
setupThreeJs() {
  // ...

  // this.scene = DemoUtils.createCubeScene();
  this.scene = DemoUtils.createLitScene();
  this.reticle = new Reticle();
  this.scene.add(this.reticle);
}

Untuk melakukan hit test, gunakan XRReferenceSpace yang baru. Ruang referensi ini menunjukkan sistem koordinat baru dari perspektif penampil untuk membuat sinar yang sejajar dengan arah tampilan. Sistem koordinat ini digunakan di XRSession.requestHitTestSource(), yang dapat menghitung hit test.

  1. Tambahkan kode berikut ke onSessionStarted() di app.js:
async onSessionStarted() {
  // ...

  // Setup an XRReferenceSpace using the "local" coordinate system.
  this.localReferenceSpace = await this.xrSession.requestReferenceSpace("local");

  // Add these lines:
  // Create another XRReferenceSpace that has the viewer as the origin.
  this.viewerSpace = await this.xrSession.requestReferenceSpace("viewer");
  // Perform hit testing using the viewer as origin.
  this.hitTestSource = await this.xrSession.requestHitTestSource({ space: this.viewerSpace });

  // ...
}
  1. Dengan hitTestSource ini, lakukan hit test setiap frame:
    • Jika tidak ada hasil yang keluar setelah melakukan hit test, artinya ARCore belum memiliki cukup waktu untuk membangun pemahaman tentang lingkungan sekitarnya. Dalam hal ini, minta pengguna untuk memindahkan perangkat menggunakan stabilisasi <div>.
    • Jika ada hasilnya, pindahkan reticle ke lokasi tersebut.
  2. Ubah onXRFrame untuk memindahkan reticle tersebut:
onXRFrame = (time, frame) => {
  // ... some code omitted ...
  this.camera.updateMatrixWorld(true);

  // Add the following:
  const hitTestResults = frame.getHitTestResults(this.hitTestSource);

  if (!this.stabilized && hitTestResults.length > 0) {
    this.stabilized = true;
    document.body.classList.add("stabilized");
  }
  if (hitTestResults.length > 0) {
    const hitPose = hitTestResults[0].getPose(this.localReferenceSpace);

    // update the reticle position
    this.reticle.visible = true;
    this.reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
    this.reticle.updateMatrixWorld(true);
  }
  // More code omitted.
}

Menambahkan perilaku pada ketukan layar

XRSession dapat memunculkan peristiwa berdasarkan interaksi pengguna melalui peristiwa select, yang mewakili tindakan utama. Di WebXR pada perangkat seluler, tindakan utamanya adalah ketukan layar.

  1. Tambahkan pemroses peristiwa select di bagian bawah onSessionStarted:
this.xrSession.addEventListener("select", this.onSelect);

Dalam contoh ini, ketukan layar menyebabkan bunga matahari ditempatkan di reticle.

  1. Buat implementasi untuk onSelect di class App:
onSelect = () => {
  if (window.sunflower) {
    const clone = window.sunflower.clone();
    clone.position.copy(this.reticle.position);
    this.scene.add(clone);
  }
}

Menguji aplikasi

Anda membuat reticle yang dapat ditargetkan menggunakan perangkat Anda menggunakan hit test. Saat mengetuk layar, Anda dapat menempatkan bunga matahari di lokasi yang ditunjuk reticle.

  1. Saat menjalankan aplikasi, Anda akan dapat melihat reticle yang melacak permukaan lantai. Jika tidak, coba lihat sekeliling secara perlahan dengan ponsel Anda.
  2. Ketuk reticle setelah Anda melihatnya. Bunga matahari harus ditempatkan di atasnya. Anda mungkin harus bergerak sedikit demi sedikit sehingga platform AR yang mendasarinya dapat mendeteksi permukaan dunia nyata dengan lebih baik. Pencahayaan rendah dan permukaan yang datar akan mengurangi kualitas pemahaman scene, dan meningkatkan peluang tidak ditemukannya hit. Jika Anda mengalami masalah, lihat kode step-04/app.js untuk melihat contoh kerja langkah ini.

5. Menambahkan bayangan

Membuat scene yang realistis melibatkan elemen seperti pencahayaan dan bayangan yang tepat pada objek digital yang akan menambahkan realisme dan detail imersif dalam scene tersebut.

Pencahayaan dan bayangan ditangani oleh three.js. Anda dapat menentukan cahaya mana yang harus memunculkan bayangan, material mana yang harus menerima dan merender bayangan ini, dan mesh mana yang dapat memunculkan bayangan. Scene pada aplikasi ini berisi cahaya yang dapat memunculkan bayangan dan permukaan datar hanya untuk merender bayangan.

  1. Aktifkan bayangan di three.js WebGLRenderer. Setelah membuat perender, setel nilai berikut pada shadowMap-nya:
setupThreeJs() {
  ...
  this.renderer = new THREE.WebGLRenderer(...);
  ...
  this.renderer.shadowMap.enabled = true;
  this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  ...
}

Contoh scene yang dibuat dalam DemoUtils.createLitScene() berisi objek yang disebut shadowMesh, permukaan horizontal datar yang hanya merender bayangan. Permukaan ini awalnya memiliki posisi Y berisi 10.000 unit. Setelah bunga matahari ditempatkan, pindahkan shadowMesh agar tingginya sama dengan permukaan dunia nyata, sehingga bayangan bunga dirender di atas tanah dunia nyata.

  1. Di onSelect, setelah menambahkan clone ke scene tersebut, tambahkan kode untuk memposisikan ulang bidang bayangannya:
onSelect = () => {
  if (window.sunflower) {
    const clone = window.sunflower.clone();
    clone.position.copy(this.reticle.position);
    this.scene.add(clone);

    const shadowMesh = this.scene.children.find(c => c.name === "shadowMesh");
    shadowMesh.position.y = clone.position.y;
  }
}

Melakukan pengujian

Saat menempatkan bunga matahari, Anda dapat melihatnya memunculkan bayangan. Jika Anda mengalami masalah, lihat kode final/app.js untuk melihat contoh kerja langkah ini.

6. Referensi lainnya

Selamat! Anda sudah mencapai akhir bagian codelab ini mengenai AR menggunakan WebXR.

Pelajari lebih lanjut