سترشدك هذه الصفحة خلال عملية إنشاء تطبيق الواقع المعزّز البسيط والغامر باستخدام WebXR.
ستحتاج إلى بيئة تطوير متوافقة مع WebXR للبدء.
إنشاء صفحة HTML
يتطلب WebXR تفاعل المستخدم حتى يتمكن من بدء جلسة.
إنشاء زر للاتصال بـ activateXR()
. عند تحميل الصفحة، يمكن للمستخدم استخدام هذا الزر لبدء تجربة "الواقع المعزّز".
أنشئ ملفًا جديدًا باسم index.html
وأضِف رمز HTML التالي إليه:
<!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>
إعداد three.js
لن يحدث الكثير عند الضغط على زر Start (البدء). لإعداد بيئة ثلاثية الأبعاد، يمكنك استخدام مكتبة عرض لعرض مشهد.
في هذا المثال، ستستخدم three.js
، وهي مكتبة عرض JavaScript ثلاثي الأبعاد توفّر عارض WebGL. يعالج Three.js
العرض والكاميرات والرسوم البيانية للمشهد، ما يسهّل عرض المحتوى الثلاثي الأبعاد على الويب.
إنشاء مشهد
يتم تصميم البيئة ثلاثية الأبعاد بشكل عام على أنها مشهد. أنشِئ عنصر THREE.Scene
يحتوي على عناصر الواقع المعزّز.
يسمح لك الرمز التالي بإلقاء نظرة على مربع ملوّن غير مضاء في الواقع المعزّز.
أضِف هذا الرمز إلى أسفل دالة 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);
إعداد العرض باستخدام three.js
لتتمكن من عرض هذا المشهد في الواقع المعزّز، ستحتاج إلى عارض وكاميرا. يستخدم العارض WebGL لرسم المشهد على الشاشة. تصف الكاميرا إطار العرض الذي يتم عرض المشهد منه.
أضِف هذا الرمز إلى أسفل دالة 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;
إنشاء جلسة XRSession
تكون نقطة الدخول إلى WebXR من خلال XRSystem.requestSession()
. استخدِم وضع immersive-ar
للسماح بعرض المحتوى المعروض في بيئة حقيقية.
تصف السمة XRReferenceSpace
نظام الإحداثيات المستخدَم للكائنات داخل العالم الافتراضي.
يناسب وضع "'local'
" تجربة الواقع المعزّز، مع مساحة مرجعية لها مصدرها قريب من العارض ونظام تتبّع ثابت.
لإنشاء XRSession
وXRReferenceSpace
، أضِف هذا الرمز إلى أسفل دالة 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');
عرض المشهد
الآن يمكنك عرض المشهد. تعمل XRSession.requestAnimationFrame()
على جدولة استدعاء يتم تنفيذه عندما يكون المتصفِّح جاهزًا لرسم إطار.
أثناء معاودة الاتصال بإطار الصورة المتحركة، يمكنك استدعاء الرمز XRFrame.getViewerPose()
للحصول على وضع المشاهد بالنسبة إلى مساحة الإحداثيات المحلية.
والهدف من ذلك هو تحديث كاميرا داخل المشهد وتغيير نظرة المستخدم للعالم الافتراضي قبل أن يرسم العارض المشهد باستخدام الكاميرا المحدَّثة.
أضِف هذا الرمز إلى أسفل دالة 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);
تشغيل Hello WebXR
انتقِل إلى ملف WebXR على جهازك. يجب أن تتمكن من عرض مكعب ملون من جميع الجوانب.
إضافة اختبار ناتج
هناك طريقة شائعة للتفاعل مع عالم الواقع المعزّز تتمثل في استخدام اختبار نتيجة يعثر على تقاطع بين الأشعة والهندسة في العالم الحقيقي. في Hello WebXR، ستستخدم اختبارًا ناجحًا لوضع زهرة دوار الشمس في العالم الافتراضي.
إزالة المكعّب التجريبي
أزل المكعّب غير المضاء واستبدله بمشهد يحتوي على إضاءة:
const scene = new THREE.Scene();
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);
استخدام ميزة "hit-test
"
لإعداد وظيفة اختبار النتائج، اطلب جلسة باستخدام ميزة hit-test
. ابحث عن الجزء requestSession()
السابق وأضِف hit-test
إليه:
const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});
إضافة أداة تحميل نموذج
في الوقت الحالي، يحتوي المشهد على مكعب ملون فقط. لجعل التجربة أكثر إثارة للاهتمام، أضِف أداة تحميل نماذج، ما يسمح بتحميل نماذج GLTF.
في علامة <head>
لمستندك، أضِف three.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>
تحميل طُرز GLTF
استخدم أداة تحميل النموذج من الخطوة السابقة لتحميل شبكة استهداف وزر دوار من الويب.
أضِف هذا الرمز أعلى 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) => {
إنشاء مصدر اختبار نتائج
لحساب التقاطعات مع كائنات واقعية، أنشِئ XRHitTestSource
باستخدام السمة
XRSession.requestHitTestSource()
.
يحتوي الشعاع المستخدَم لاختبار النتائج على المساحة المرجعية viewer
كنقطة انطلاق، ما يعني أنّ اختبار النتيجة يتم من منتصف إطار العرض.
لإنشاء مصدر اختبار نتائج، أضِف هذا الرمز بعد إنشاء المساحة المرجعية 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 });
رسم شبكة استهداف
لتوضيح مكان وضع زهرة الشمس، أضف شبكة استهداف إلى المشهد. ستظهر هذه الشبكة ملتصقة بأسطح حقيقية، مما يشير إلى مكان تثبيت دوار الشمس.
تعرض XRFrame.getHitTestResults
صفيفًا من XRHitTestResult
وتعرض التقاطعات بهندسة حقيقية.
استخدم هذه التقاطعات لوضع شبكة الاستهداف على كل إطار.
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);
}
إضافة تفاعلات عند النقر
يتلقّى XRSession
select
حدث عندما يُكمل المستخدم إجراءً أساسيًا.
في جلسة الواقع المعزّز، يتجاوب هذا مع النقر على الشاشة.
جعل زهرة دوار الشمس جديدة تظهر عندما ينقر المستخدم على الشاشة عن طريق إضافة هذه التعليمة البرمجية أثناء الإعداد:
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);
}
});
اختبار النتائج
استخدِم جهازك الجوّال للانتقال إلى الصفحة. بعد أن تقوم WebXR بفهم البيئة، يجب أن تظهر الشبكة على أسطح العالم الحقيقي. انقر على الشاشة لوضع زهرة دوار الشمس، والتي يمكن عرضها من جميع الجوانب.
الخطوات التالية
- اطّلِع على مواصفات WebXR Device API.
- اطّلِع على مستندات WebXR المرجعية حول مستندات الويب MDN.
- يمكنك تجربة نماذج WebXR.
- إنشاء تطبيق الواقع المعزّز (AR) باستخدام WebXR Device API (الدرس التطبيقي حول الترميز)