Virtual reality hadir di web

Beberapa dasar untuk mempersiapkan Anda mendapatkan spektrum pengalaman yang imersif: virtual reality, augmented reality, dan banyak lagi.

Joe Medley
Joe Medley

Pengalaman imersif hadir di web pada Chrome 79. WebXR Device API menghadirkan virtual reality yang menghadirkan virtual reality, sedangkan dukungan untuk augmented reality tiba di Chrome 81. Sementara update untuk GamePad API memperluas penggunaan kontrol lanjutan ke VR. Browser lainnya akan segera mendukung spesifikasi ini, termasuk Firefox Reality, Oculus Browser, Edge, dan browser Helio Magic Leap, di antaranya.

Artikel ini memulai seri artikel di web imersif. Tutorial ini mencakup penyiapan aplikasi WebXR dasar serta masuk dan keluar dari sesi XR. Artikel selanjutnya akan membahas frame loop (pekerja keras pengalaman WebXR), spesifikasi augmented reality, dan WebXR Hit Test API, yakni cara mendeteksi platform dalam sesi AR. Kecuali jika dinyatakan sebaliknya, semua yang saya bahas dalam artikel ini dan artikel berikutnya juga berlaku untuk AR dan VR.

Apa itu web imersif?

Meskipun kami menggunakan dua istilah untuk menggambarkan pengalaman imersif—realitas yang ditingkatkan dan virtual reality—banyak yang memikirkannya dalam spektrum dari realitas penuh hingga sepenuhnya virtual, dengan derajat pengalaman yang begitu mendalam di antaranya. 'X' di XR dimaksudkan untuk mencerminkan pemikiran tersebut dengan menjadi variabel aljabar yang mewakili apa pun dalam spektrum pengalaman yang imersif.

Grafik yang menggambarkan spektrum pengalaman visual dari realitas yang lengkap hingga yang benar-benar imersif.
Ragam pengalaman yang imersif

Contoh pengalaman yang imersif meliputi:

  • Game
  • Video 360°
  • Video 2D (atau 3D) tradisional yang disajikan di lingkungan yang imersif
  • Pembelian rumah
  • Melihat produk di rumah Anda sebelum membelinya
  • Seni imersif
  • Sesuatu yang keren belum ada yang terlintas di pikiran

Konsep dan penggunaan

Saya akan menjelaskan beberapa dasar penggunaan WebXR Device API. Jika Anda memerlukan informasi yang lebih mendalam daripada yang saya berikan, lihat contoh WebXR dari Immersive Web Working Group atau materi referensi yang terus berkembang dari MDN. Jika sudah terbiasa dengan WebXR Device API versi awal, Anda harus melihat semua materi ini secara sekilas. Ada beberapa perubahan.

Kode dalam artikel ini didasarkan pada contoh barebone Immersive Web Working Group (demo, sumber), tetapi diedit agar lebih jelas dan mudah.

Bagian dari pembuatan spesifikasi WebXR adalah memperjelas langkah-langkah keamanan dan privasi untuk melindungi pengguna. Akibatnya, implementasi harus mematuhi persyaratan tertentu. Halaman web atau aplikasi harus aktif dan fokus sebelum dapat meminta informasi sensitif dari penonton. Halaman web atau aplikasi harus ditayangkan melalui HTTPS. API itu sendiri dirancang untuk melindungi informasi yang diperoleh dari sensor dan kamera, yang diperlukannya agar dapat berfungsi.

Meminta sesi

Memasuki sesi XR memerlukan gestur pengguna. Untuk mendapatkannya, gunakan deteksi fitur untuk menguji XRSystem (melalui navigator.xr) dan lakukan panggilan ke XRSystem.isSessionSupported(). Perlu diketahui bahwa pada Chrome versi 79 dan 80, objek XRSystem disebut XR.

Pada contoh di bawah, saya telah menyatakan bahwa saya ingin sesi virtual reality dengan jenis sesi 'immersive-vr'. Jenis sesi lainnya adalah 'immersive-ar' dan 'inline'. Sesi inline digunakan untuk menyajikan konten dalam HTML dan terutama digunakan untuk konten teaser. Contoh Sesi AR Imersif menunjukkan hal ini. Saya akan menjelaskannya di artikel selanjutnya.

Setelah mengetahui bahwa sesi virtual reality didukung, saya mengaktifkan tombol yang memungkinkan saya mendapatkan gestur pengguna.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter VR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

Setelah mengaktifkan tombol, saya menunggu peristiwa klik kemudian meminta sesi.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-vr')
    .then((session) => {
      xrSession = session;
      xrButton.textContent = 'Exit XR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

Perhatikan hierarki objek dalam kode ini. Fungsi ini berpindah dari navigator ke xr ke instance XRSession. Pada versi awal API, skrip harus meminta perangkat sebelum meminta sesi. Sekarang, perangkat diperoleh secara implisit.

Masukkan sesi

Setelah mendapatkan sesi, saya harus memulainya dan memasukkannya. Tapi pertama-tama, saya perlu menyiapkan beberapa hal. Sesi memerlukan pengendali peristiwa onend agar aplikasi atau halaman web dapat direset saat pengguna keluar.

Saya juga memerlukan elemen <canvas> untuk menggambar adegan saya. Properti tersebut harus berupa WebGLRenderingContext atau WebGL2RenderingContext yang kompatibel dengan XR. Semua menggambar dilakukan menggunakan framework tersebut atau framework berbasis WebGL seperti Three.js.

Sekarang saya memiliki tempat untuk menggambar, saya membutuhkan sumber konten untuk menggambarnya. Untuk itu, saya membuat instance XRWebGLLayer. Saya mengaitkannya dengan kanvas dengan memanggil XRSession.updateRenderState().

Begitu berada dalam sesi, saya membutuhkan cara untuk menentukan letak segala sesuatu dalam realitas virtual. Saya memerlukan ruang referensi. Ruang referensi 'local-floor' adalah ruang yang asalnya berada di dekat penampil dan sumbu y adalah 0 di tingkat lantai dan tidak diharapkan untuk bergerak. Ada jenis ruang referensi lainnya, tetapi ini adalah topik yang lebih rumit daripada yang bisa saya bahas di sini. Saya menyimpan ruang referensi untuk variabel karena saya akan membutuhkannya saat menggambar ke layar.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

Setelah mendapatkan ruang referensi, saya memanggil XRSession.requestAnimationFrame(). Ini adalah awal penyajian konten virtual, yang dilakukan dalam loop frame.

Menjalankan loop frame

Frame loop adalah loop tanpa batas yang dikontrol agen pengguna, yang menggambarkan konten berulang kali ke layar. Konten digambar dalam blok terpisah yang disebut frame. Suksesi bingkai menciptakan ilusi gerakan. Untuk aplikasi VR, frame per detik dapat berkisar dari 60 hingga 144. AR untuk Android berjalan pada 30 frame per detik. Kode Anda tidak boleh mengasumsikan kecepatan frame tertentu.

Proses dasar untuk loop frame adalah:

  1. Panggil XRSession.requestAnimationFrame(). Sebagai respons, agen pengguna akan memanggil XRFrameRequestCallback, yang Anda tentukan.
  2. Di dalam fungsi callback:
    1. Telepon XRSession.requestAnimationFrame() lagi.
    2. Lihat pose penonton.
    3. Teruskan ('ikat') WebGLFramebuffer dari XRWebGLLayer ke WebGLRenderingContext.
    4. Lakukan iterasi pada setiap objek XRView, mengambil XRViewport dari XRWebGLLayer dan meneruskannya ke WebGLRenderingContext.
    5. Gambar sesuatu ke framebuffer.

Bagian selanjutnya dari artikel ini menjelaskan langkah 1 dan bagian dari langkah 2, yaitu menyiapkan dan memanggil XRFrameRequestCallback. Item lainnya dari langkah 2 dibahas di bagian II.

XRFrameRequestCallback

XRFrameRequestCallback ditentukan oleh Anda. Di sini terdapat dua parameter: instance DOMHighResTimeStamp dan XRFrame. Objek XRFrame memberikan informasi yang diperlukan untuk merender satu frame ke layar. Argumen DOMHighResTimeStamp digunakan untuk penggunaan di masa mendatang.

Sebelum melakukan hal lain, saya akan meminta {i>frame<i} animasi berikutnya. Seperti yang disebutkan sebelumnya, waktu render frame ditentukan oleh agen pengguna berdasarkan hardware yang mendasarinya. Meminta frame berikutnya terlebih dahulu akan memastikan bahwa loop frame berlanjut jika sesuatu selama callback menampilkan error.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  // Render a frame.
}

Pada tahap ini, saatnya menggambar sesuatu untuk penonton. Itulah diskusi untuk bagian II. Sebelum melanjutkan, saya akan tunjukkan cara mengakhiri sesi.

Mengakhiri sesi

Sesi imersif dapat berakhir karena beberapa alasan, termasuk diakhiri oleh kode Anda sendiri melalui panggilan ke XRSession.end(). Penyebab lainnya adalah headset terputus atau aplikasi lain mengambil alih kontrolnya. Itulah sebabnya aplikasi yang berperilaku baik harus memantau peristiwa end. Saat terjadi, hapus sesi tersebut dan objek render terkaitnya. Sesi imersif yang telah berakhir tidak dapat dilanjutkan. Untuk masuk kembali ke pengalaman imersif, aplikasi saya harus memulai sesi baru.

Ingat kembali dari bagian Memasuki sesi bahwa selama penyiapan, saya menambahkan pengendali peristiwa onend.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);
  // More setup…
}

Di dalam pengendali peristiwa, pulihkan status aplikasi sebelum pengguna memasuki sesi.

function onSessionEnded(event) {
  xrSession = null;
  xrButton.textContent = 'Enter VR';
}

Kesimpulan

Saya belum menjelaskan semua yang Anda perlukan untuk menulis aplikasi Web XR atau AR. Mudah-mudahan, saya sudah memberi Anda cukup untuk mulai memahami kode Anda sendiri, dan cukup untuk mulai bereksperimen. Dalam artikel berikutnya, saya akan menjelaskan {i> frame loop<i}, yaitu tempat konten digambar ke layar.

Foto oleh JESHOOTS.COM di Unsplash