WEBXR AUGMENTED-REALITY VIRTUAL-REALITY MIXED-REALITY WEB-DEVELOPMENT BROWSER-API 3D-GRAPHICS INTERACTIVE-WEB FRONTEND JAVASCRIPT WEB-PERFORMANCE

WebXR: Membangun Pengalaman Augmented Reality dan Virtual Reality Langsung di Browser Anda

⏱️ 19 menit baca
👨‍💻

WebXR: Membangun Pengalaman Augmented Reality dan Virtual Reality Langsung di Browser Anda

1. Pendahuluan

Pernahkah Anda membayangkan bisa menempatkan furnitur virtual di ruang tamu Anda sebelum membelinya, atau menjelajahi galeri seni 3D dari kenyamanan browser web Anda? Dulu, pengalaman seperti Augmented Reality (AR) dan Virtual Reality (VR) membutuhkan aplikasi khusus atau perangkat lunak yang rumit. Namun, berkat WebXR Device API, semua itu kini bisa diwujudkan langsung di browser web!

WebXR adalah sebuah standar web yang memungkinkan developer untuk membangun pengalaman realitas campuran (AR, VR, dan MR) yang imersif dan interaktif, dapat diakses hanya dengan sebuah URL. Ini membuka pintu bagi potensi tak terbatas untuk e-commerce, pendidikan, gaming, visualisasi data, dan banyak lagi, tanpa perlu instalasi aplikasi tambahan.

Artikel ini akan membawa Anda menyelami dunia WebXR. Kita akan memahami konsep dasarnya, menyiapkan lingkungan pengembangan, dan bahkan membangun contoh sederhana pengalaman VR dan AR menggunakan JavaScript dan library Three.js. Bersiaplah untuk membawa aplikasi web Anda ke dimensi yang benar-benar baru! 🚀

2. Memahami Dunia Realitas Campuran: AR, VR, dan MR

Sebelum kita mulai ngoding, mari kita samakan persepsi tentang istilah-istilah di dunia realitas campuran:

WebXR Device API adalah payung besar yang mendukung ketiga jenis pengalaman ini di web. Ini menyediakan jembatan antara browser dan perangkat XR (seperti headset VR, smartphone dengan kemampuan AR, atau kacamata pintar AR).

3. Bagaimana WebXR Bekerja di Browser?

WebXR bekerja dengan mengekspos serangkaian antarmuka JavaScript yang memungkinkan aplikasi web untuk:

  1. Mendeteksi Perangkat XR: Mengecek apakah ada perangkat XR yang tersedia dan kompatibel.
  2. Membuat Sesi XR: Memulai sesi VR atau AR, yang menentukan jenis pengalaman (misalnya, VR imersif, AR passthrough).
  3. Mengakses Pose Perangkat: Mendapatkan posisi dan orientasi perangkat (headset atau smartphone) di dunia nyata atau virtual.
  4. Menggambar ke Layar: Menyediakan buffer untuk merender grafis 3D yang akan ditampilkan di perangkat XR.
  5. Menangani Input: Menerima input dari controller XR atau interaksi sentuhan di layar smartphone.

📌 Penting: Untuk alasan keamanan dan privasi, WebXR hanya dapat berjalan di situs web yang menggunakan HTTPS. Ini memastikan bahwa data sensor perangkat yang sensitif ditransmisikan dengan aman.

4. Persiapan Lingkungan Pengembangan WebXR

Untuk memulai, kita hanya membutuhkan beberapa hal:

5. Membangun Pengalaman VR Sederhana dengan Three.js dan WebXR

Mari kita buat pengalaman VR sederhana: sebuah kubus yang melayang di ruang virtual.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebXR VR Kubus</title>
    <style>
        body { margin: 0; overflow: hidden; }
        #vr-button {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            padding: 10px 20px;
            font-size: 1.2em;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            z-index: 100;
        }
    </style>
</head>
<body>
    <script type="module">
        import * as THREE from 'https://unpkg.com/three/build/three.module.js';
        import { VRButton } from 'https://unpkg.com/three/examples/jsm/webxr/VRButton.js';

        let camera, scene, renderer;
        let cube;

        init();
        animate();

        function init() {
            // 1. Scene
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x505050);

            // 2. Camera
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 1.6, 3); // Posisi awal kamera

            // 3. Renderer
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.xr.enabled = true; // Aktifkan WebXR di renderer
            document.body.appendChild(renderer.domElement);

            // 4. Objek 3D (Kubus)
            const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
            const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
            cube = new THREE.Mesh(geometry, material);
            cube.position.set(0, 1.6, -1); // Letakkan kubus di depan kamera
            scene.add(cube);

            // 5. Tambahkan cahaya untuk melihat objek
            const light = new THREE.HemisphericLight(0xffffff, 0xbbbbff, 1);
            light.position.set(0.5, 1, 0.25);
            scene.add(light);

            // 6. Tombol "Enter VR"
            document.body.appendChild(VRButton.createButton(renderer));

            // Tangani perubahan ukuran jendela
            window.addEventListener('resize', onWindowResize);
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        function animate() {
            renderer.setAnimationLoop(render); // Gunakan setAnimationLoop untuk WebXR
        }

        function render() {
            // Rotasi kubus
            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;

            renderer.render(scene, camera);
        }
    </script>
</body>
</html>

Penjelasan Kode:

  1. Setup Dasar Three.js: Kita membuat Scene, Camera, dan Renderer seperti biasa.
  2. renderer.xr.enabled = true;: Ini adalah baris kunci yang memberitahu Three.js untuk mengaktifkan mode WebXR.
  3. VRButton.createButton(renderer): Helper dari Three.js ini secara otomatis membuat tombol “Enter VR” yang menangani logika untuk memulai dan mengakhiri sesi VR. Jika perangkat tidak mendukung VR, tombol akan dinonaktifkan.
  4. renderer.setAnimationLoop(render): Ini adalah loop render khusus WebXR. Daripada requestAnimationFrame biasa, setAnimationLoop memastikan rendering dioptimalkan untuk perangkat XR, memanggil fungsi render setiap kali frame baru siap ditampilkan di headset.
  5. Objek 3D: Kita menambahkan kubus sederhana dan sedikit cahaya agar terlihat.

Untuk menjalankannya, simpan kode di atas sebagai index.html dan jalankan server lokal Anda dengan HTTPS. Buka di browser di perangkat yang mendukung VR (misalnya, headset VR yang terhubung ke PC, atau smartphone dengan Google Cardboard jika browser mendukung). Klik tombol “Enter VR” dan Anda akan melihat kubus berputar di dunia virtual! ✅

6. Membangun Pengalaman AR Sederhana dengan Three.js dan WebXR

Sekarang, mari kita coba pengalaman AR. Kita akan menempatkan kubus virtual di dunia nyata menggunakan kamera perangkat Anda.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebXR AR Kubus</title>
    <style>
        body { margin: 0; overflow: hidden; }
        #ar-button {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            padding: 10px 20px;
            font-size: 1.2em;
            background-color: #28a745;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            z-index: 100;
        }
    </style>
</head>
<body>
    <script type="module">
        import * as THREE from 'https://unpkg.com/three/build/three.module.js';
        import { ARButton } from 'https://unpkg.com/three/examples/jsm/webxr/ARButton.js';

        let camera, scene, renderer;
        let controller;
        let cube;
        let hitTestSource = null;
        let hitTestSourceRequested = false;

        init();
        animate();

        function init() {
            // 1. Scene
            scene = new THREE.Scene();

            // 2. Camera (akan diatur oleh WebXR)
            camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 20);

            // 3. Renderer
            renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); // alpha: true untuk latar belakang transparan
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.xr.enabled = true;
            document.body.appendChild(renderer.domElement);

            // 4. Tombol "Enter AR"
            document.body.appendChild(ARButton.createButton(renderer, { requiredFeatures: ['hit-test', 'dom-overlay'], domOverlay: { root: document.body } }));

            // 5. Controller (untuk interaksi, misal touch di layar)
            controller = renderer.xr.getController(0);
            controller.addEventListener('select', onSelect);
            scene.add(controller);

            // 6. Tambahkan cahaya
            const light = new THREE.HemisphericLight(0xffffff, 0xbbbbff, 1);
            light.position.set(0.5, 1, 0.25);
            scene.add(light);

            // Tangani perubahan ukuran jendela
            window.addEventListener('resize', onWindowResize);
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        function onSelect() {
            if (hitTestSource) {
                if (cube) { // Hapus kubus lama jika ada
                    scene.remove(cube);
                    cube = null;
                }
                const referenceSpace = renderer.xr.getReferenceSpace();
                const hitTestResults = renderer.xr.getSession().requestHitTestSource(hitTestSource, referenceSpace);

                hitTestResults.then(results => {
                    if (results.length > 0) {
                        const hit = results[0];
                        const pose = hit.getPose(referenceSpace);

                        // Buat kubus baru
                        const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
                        const material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.8 });
                        cube = new THREE.Mesh(geometry, material);
                        cube.position.copy(pose.transform.position);
                        cube.quaternion.copy(pose.transform.rotation);
                        scene.add(cube);
                    }
                });
            }
        }

        function animate() {
            renderer.setAnimationLoop(render);
        }

        function render(timestamp, frame) {
            if (frame) {
                const session = renderer.xr.getSession();
                const referenceSpace = renderer.xr.getReferenceSpace();

                if (hitTestSourceRequested === false) {
                    session.requestReferenceSpace('viewer').then(viewerSpace => {
                        session.requestHitTestSource({ space: viewerSpace }).then(source => {
                            hitTestSource = source;
                        });
                    });
                    session.addEventListener('end', () => {
                        hitTestSourceRequested = false;
                        hitTestSource = null;
                    });
                    hitTestSourceRequested = true;
                }

                if (hitTestSource) {
                    const hitTestResults = frame.getHitTestResults(hitTestSource);
                    if (hitTestResults.length > 0) {
                        const hit = hitTestResults[0];
                        const pose = hit.getPose(referenceSpace);
                        // Anda bisa menempatkan indikator di sini jika ingin menunjukkan di mana objek akan muncul
                        // Misalnya, sebuah cincin di tanah
                    }
                }
            }

            renderer.render(scene, camera);
        }
    </