Halaman ini akan memandu Anda membuat aplikasi AR imersif sederhana menggunakan WebXR.
Anda memerlukan lingkungan pengembangan yang kompatibel dengan WebXR untuk memulai.
Membuat halaman HTML
WebXR memerlukan interaksi pengguna agar dapat memulai sesi.
Buat tombol yang memanggil activateXR()
. Setelah memuat halaman, pengguna dapat menggunakan tombol ini untuk memulai pengalaman AR.
Buat file baru bernama index.html
dan tambahkan kode HTML berikut ke dalamnya:
<!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>
Melakukan inisialisasi three.js
Tidak banyak yang akan terjadi saat menekan tombol Start. Untuk menyiapkan lingkungan 3D, Anda dapat menggunakan library rendering untuk menampilkan tampilan.
Dalam contoh ini, Anda akan menggunakan three.js
, library rendering 3D JavaScript yang menyediakan perender WebGL. Three.js
menangani rendering, kamera, dan grafik tampilan, sehingga mempermudah tampilan konten 3D di web.
Membuat scene
Lingkungan 3D biasanya dimodelkan sebagai tampilan. Buat THREE.Scene
yang berisi elemen AR.
Kode berikut memungkinkan Anda melihat kotak berwarna yang tidak menyala di AR.
Tambahkan kode ini ke bagian bawah fungsi 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);
Menyiapkan rendering menggunakan three.js
Agar dapat melihat tampilan ini dalam AR, Anda memerlukan perender dan kamera. Perender menggunakan WebGL untuk menggambar tampilan ke layar. Kamera menjelaskan area tampilan tempat tampilan dilihat.
Tambahkan kode ini ke bagian bawah fungsi 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;
Membuat XRSession
Titik entri ke WebXR adalah melalui XRSystem.requestSession()
. Gunakan mode immersive-ar
agar konten yang dirender dapat dilihat di lingkungan dunia nyata.
XRReferenceSpace
menjelaskan sistem koordinat yang digunakan untuk objek dalam dunia virtual.
Mode 'local'
sangat cocok digunakan untuk pengalaman AR, dengan ruang referensi yang memiliki asal di dekat penampil dan pelacakan yang stabil.
Untuk membuat XRSession
dan XRReferenceSpace
, tambahkan kode ini ke bagian bawah fungsi 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');
Render tampilan
Sekarang Anda dapat merender tampilan. XRSession.requestAnimationFrame()
menjadwalkan callback yang dijalankan saat browser siap menggambar frame.
Selama callback frame animasi, panggil XRFrame.getViewerPose()
untuk mendapatkan pose penampil yang relatif terhadap ruang koordinat lokal.
Ini digunakan untuk memperbarui kamera dalam tampilan, mengubah cara pengguna melihat dunia virtual sebelum perender menggambar tampilan menggunakan kamera yang diperbarui.
Tambahkan kode ini ke bagian bawah fungsi 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);
Menjalankan Hello WebXR
Buka file WebXR di perangkat Anda. Anda akan dapat melihat kubus berwarna dari semua sisi.
Menambahkan hit test
Cara umum untuk berinteraksi dengan dunia AR adalah melalui hit test, yang menemukan titik potong antara sinar dan geometri dunia nyata. Di Hello WebXR, Anda akan menggunakan hit test untuk menempatkan bunga matahari di dunia virtual.
Menghapus kubus demo
Hapus kubus yang tidak diterangi dan ganti dengan tampilan yang menyertakan pencahayaan:
const scene = new THREE.Scene();
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);
Menggunakan fitur hit-test
Untuk melakukan inisialisasi fungsi hit test, minta sesi dengan fitur hit-test
. Temukan fragmen requestSession()
sebelumnya, lalu tambahkan hit-test
ke dalamnya:
const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});
Menambahkan loader model
Saat ini, tampilan hanya berisi kubus berwarna. Untuk membuat pengalaman lebih menarik, tambahkan loader model, yang memungkinkan model GLTF dimuat.
Di tag <head>
dokumen Anda, tambahkan GLTFLoader
three.js.
<!-- 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>
Memuat model GLTF
Gunakan loader model dari langkah sebelumnya untuk memuat reticle penargetan dan bunga matahari dari web.
Tambahkan kode ini di atas 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) => {
Membuat sumber hit test
Untuk menghitung persimpangan dengan objek dunia nyata, buat XRHitTestSource
menggunakan
XRSession.requestHitTestSource()
.
Ray yang digunakan untuk hit test memiliki ruang referensi viewer
sebagai asal, yang berarti hit test dilakukan dari tengah area pandang.
Untuk membuat sumber hit test, tambahkan kode ini setelah membuat ruang referensi 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 });
Menggambar reticle penargetan
Untuk memperjelas tempat bunga matahari akan ditempatkan, tambahkan reticle penargetan ke tampilan. Reticle ini akan tampak menempel pada permukaan dunia nyata, yang menunjukkan tempat bunga matahari akan ditambatkan.
XRFrame.getHitTestResults
menampilkan array XRHitTestResult
dan mengekspos persimpangan dengan geometri dunia nyata.
Gunakan persimpangan ini untuk memosisikan reticle penargetan di setiap frame.
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);
}
Menambahkan interaksi saat diketuk
XRSession
menerima peristiwa select
saat pengguna menyelesaikan tindakan utama.
Dalam sesi AR, ini sesuai dengan ketukan di layar.
Buat bunga matahari baru muncul saat pengguna mengetuk layar dengan menambahkan kode ini selama inisialisasi:
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);
}
});
Menguji hit test
Gunakan perangkat seluler untuk membuka halaman. Setelah WebXR membangun pemahaman tentang lingkungan, reticle akan muncul di permukaan dunia nyata. Ketuk layar untuk menempatkan bunga matahari, yang dapat dilihat dari semua sisi.