أنشِئ جلسة الواقع المعزّز الشاملة باستخدام WebXR

سترشدك هذه الصفحة خلال عملية إنشاء تطبيق واقع معزّز شامل وبسيط باستخدام 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

لن يحدث الكثير عند الضغط على زر "ابدأ". لإعداد بيئة ثلاثية الأبعاد، يمكنك استخدام مكتبة العرض لعرض مشهد.

في هذا المثال، ستستخدم 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> في المستند، أضِف 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>

تحميل نماذج 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 البيئة، من المفترض أن تظهر شبكة الاستهداف على الأسطح في العالم الحقيقي. انقر على الشاشة لوضع زهرة عباد الشمس التي يمكن مشاهدتها من جميع الجوانب.

الخطوات التالية