إتاحة الواقع الافتراضي على الويب

إليك بعض الأساسيات التي ستساعدك في الاستعداد لمجموعة من التجارب الغامرة، مثل الواقع الافتراضي والواقع المعزّز وغير ذلك.

Joe Medley
Joe Medley

أصبحت التجارب الغامرة متاحة على الويب في الإصدار 79 من Chrome. توفّر واجهة برمجة التطبيقات WebXR Device API ميزات الواقع الافتراضي، بينما يتوفّر التوافق مع ميزات الواقع المعزّز في الإصدار 81 من Chrome. وفي حين يؤدي تحديث واجهة برمجة التطبيقات GamePad API إلى توسيع نطاق الاستخدام المتقدّم لعناصر التحكّم ليشمل الواقع الافتراضي. ستتوفّر هذه المواصفات قريبًا في متصفّحات أخرى، مثل Firefox Reality وOculus Browser وEdge ومتصفّح Helio من Magic Leap، وغير ذلك.

تبدأ هذه المقالة سلسلة عن الويب الغامر. يتناول هذا الجزء إعداد تطبيق WebXR أساسي بالإضافة إلى الدخول إلى جلسة XR والخروج منها. ستتناول المقالات اللاحقة حلقة اللقطات (أداة العمل الأساسية لتجربة WebXR)، وتفاصيل الواقع المعزّز، وWebXR Hit Test API، وهي وسيلة لرصد الأسطح في جلسة الواقع المعزّز. ما لم يُنص على خلاف ذلك، تنطبق كل المعلومات التي أتناولها في هذه المقالة والمقالات اللاحقة على كلّ من الواقع المعزّز VR والواقع المعزّز AR.

على الرغم من أنّنا نستخدم مصطلحَين لوصف التجارب التفاعلية، وهما الواقع المعزّز والواقع الافتراضي، يعتقد الكثيرون أنّهما على نطاق يتراوح بين الواقع الكامل والواقع الافتراضي الكامل، مع درجات من التفاعل بينهما. يهدف الحرف "X" في XR إلى التعبير عن هذا التفكير من خلال كونه نوعًا من المتغيّرات الجبرية التي تمثّل أي شيء في نطاق التجارب الغامرة.

رسم بياني يوضّح طيف التجارب المرئية من الواقع الكامل إلى التجربة الشاملة
مجموعة التجارب الغامرة

تشمل أمثلة التجارب الشاملة ما يلي:

  • الألعاب
  • الفيديوهات بنطاق 360 درجة
  • فيديوهات تقليدية ثنائية الأبعاد (أو ثلاثية الأبعاد) معروضة في محيط غامر
  • شراء المنازل
  • عرض المنتجات في منزلك قبل شرائها
  • الفن الغامر
  • أفكار رائعة لم يسبق لأحد التفكير بها

المفاهيم والاستخدام

سأشرح بعض الأساسيات لاستخدام WebXR Device API. إذا كنت بحاجة إلى مزيد من المعلومات العميقة مقارنةً بما قدّمته، يمكنك الاطّلاع على عيّنات WebXR التي تقدّمها مجموعة العمل "الويب الغامر" أو مواد مرجعية متزايدة الحجم في MDN. إذا كنت على دراية بالإصدارات الأولى من WebXR Device API، ننصحك بإلقاء نظرة على كل هذه المواد. حدثت تغييرات.

يستند الرمز البرمجي في هذه المقالة إلى عينة الأجزاء الأساسية من مجموعة Immersive Web Working Group (نسخة تجريبية، المصدر)، ولكن تم تعديلها لتوضيحها وبساطتها.

كان من بين أهداف إنشاء مواصفات WebXR توضيح إجراءات الأمان والخصوصية لحماية المستخدمين. وبالتالي، يجب أن تلتزم عمليات التنفيذ بمتطلبات معيّنة. يجب أن تكون صفحة الويب أو التطبيق نشطة ومركزًا قبل أن تطلب من المُشاهد أي شيء. يجب عرض صفحات الويب أو التطبيقات عبر بروتوكول HTTPS. تم تصميم واجهة برمجة التطبيقات نفسها لحماية المعلومات التي يتم الحصول عليها من الأجهزة الاستشعار والكاميرات، وهي المعلومات التي تحتاجها لكي تعمل.

طلب جلسة

يتطلب الدخول إلى جلسة الواقع المعزّز إيماءة من المستخدم. للحصول على ذلك، استخدِم ميزة رصد الميزات لاختبار "XRSystem" (عبر "navigator.xr") وإجراء مكالمة مع "XRSystem.isSessionSupported()". يُرجى العِلم أنّه في الإصدارَين 79 و80 من Chrome، كان يتمّ استدعاء XRSystem باسم XR.

في المثال أدناه، أوضحت أنّني أريد جلسة واقع افتراضي من نوع الجلسة 'immersive-vr'. أنواع الجلسات الأخرى هي 'immersive-ar' و'inline'. جلسة مضمّنة هي لعرض المحتوى داخل HTML، وتُستخدَم بشكل أساسي للمحتوى التمهيدي. يوضّح نموذج جلسة الواقع المعزّز immersive هذا الأمر. سأشرح ذلك في مقالة لاحقة.

بعد التأكّد من توفّر جلسات الواقع الافتراضي، فعِّلت زرًا يتيح لي الحصول على إيماءة المستخدم.

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
  }
}

بعد تفعيل الزر، أنتظر حدوث حدث ناتج عن النقر، ثم أطلب إجراء جلسة.

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();
  }
}

لاحِظ التدرّج الهرمي للعناصر في هذا الرمز. يتم نقله من navigator إلى xr ل إنشاء مثيل XRSession. في الإصدارات الأولى من واجهة برمجة التطبيقات، كان على النص البرمجي طلب جهاز قبل طلب جلسة. يتم الآن الحصول على الجهاز بشكل ضمني.

إدخال جلسة

بعد الحصول على جلسة، يجب بدؤها والدخول إليها. لكن أولاً، أحتاج إلى إعداد بعض الأشياء. تحتاج الجلسة إلى معالِج حدث onend حتى يمكن إعادة ضبط التطبيق أو صفحة الويب عند خروج المستخدم.

سأحتاج أيضًا إلى عنصر <canvas> لرسم المشهد عليه. يجب أن يكون WebGLRenderingContext أو WebGL2RenderingContext متوافقًا مع XR. ويتم تنفيذ جميع الرسومات باستخدامها أو باستخدام إطار عمل مستند إلى WebGL مثل Three.js.

الآن بعد أن أصبح لدي مكان للرسم، أحتاج إلى مصدر للمحتوى للاعتماد عليه. لهذا الغرض، أُنشئ مثيلًا من XRWebGLLayer. أقوم بربطه بال canvas من خلال استدعاء XRSession.updateRenderState().

بعد الانضمام إلى جلسة، أحتاج إلى طريقة لتحديد مكان الأشياء في الواقع الافتراضي. سنحتاج إلى مساحة مرجعية. المساحة المرجعية 'local-floor' هي مساحة يقع فيها مبدأ الإحداثيات بالقرب من المشاهد ويكون محور y يساوي 0 على مستوى الأرض ولا يُتوقّع أن تتحرّك. هناك أنواع أخرى من مساحات المراجع ، ولكن هذا موضوع أكثر تعقيدًا من أن أتطرق إليه هنا. أحفظ مساحة الإشارة في متغيّر لأنّني سأحتاج إليها عند الرسم على الشاشة.

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);
  });
}

بعد الحصول على مساحة مرجعية، أتصل بـ XRSession.requestAnimationFrame(). هذه هي بداية تقديم المحتوى الافتراضي، والذي يتم في حلقة الإطار.

تشغيل حلقة إطارات

حلقة عرض اللقطات هي حلقة لا نهائية يتحكّم فيها وكيل المستخدم، ويتم فيها عرض المحتوى مجددًا على الشاشة. يتم رسم المحتوى في وحدات منفصلة تُعرف باسم اللقطات. تخلق تسلسل اللقطات وهم الحركة. بالنسبة إلى تطبيقات الواقع المعزّز، يمكن أن يتراوح عدد اللقطات في الثانية بين 60 و144. يتم تشغيل ميزة "الواقع المعزّز" على أجهزة Android بمعدّل 30 لقطة في الثانية. يجب ألا تفترض التعليمات البرمجية أي معدل إطارات معين.

العملية الأساسية لتكرار الإطار هي:

  1. تواصل هاتفيًا مع "XRSession.requestAnimationFrame()". في ردّ على ذلك، يستدعي وكيل المستخدم XRFrameRequestCallback الذي تحدّده.
  2. داخل دالّة ردّ الاتصال:
    1. يُرجى الاتصال بـ XRSession.requestAnimationFrame() مرة أخرى.
    2. اضبط وضعية المشاهد.
    3. مرِّر ('اربط') WebGLFramebuffer من XRWebGLLayer إلى WebGLRenderingContext.
    4. يمكنك تكرار كل عنصر XRView، واسترداد XRViewport من XRWebGLLayer ونقله إلى WebGLRenderingContext.
    5. ارسم شيئًا على إطار التخزين المؤقت للصور.

يوضّح الجزء المتبقّي من هذه المقالة الخطوة 1 وجزءًا من الخطوة 2، وهما إعداد وتشغيل XRFrameRequestCallback. يتم تناول العناصر المتبقية من الخطوة 2 في الجزء الثاني.

دالة XRFrameRequestCallback

يمكنك تحديد XRFrameRequestCallback. يتطلب الأمر معاملين، هما: مثيل DOMHighResTimeStamp ومثيل XRFrame. يقدّم عنصر XRFrame المعلومات اللازمة لعرض إطار واحد على الشاشة. وسيطة DOMHighResTimeStamp مخصّصة للاستخدام في المستقبل.

قبل إجراء أي إجراء آخر، سأطلب إطار الصورة المتحركة التالي. كما ذكرنا سابقًا، يحدِّد وكيل المستخدم توقيت اللقطات استنادًا إلى الأجهزة الأساسية. يضمن طلب الإطار التالي أولاً مواصلة معالجة حلقة الإطارات في حال حدوث خطأ أثناء طلب البيانات.

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

في هذه المرحلة، حان وقت رسم شيء للمشاهد. سنناقش ذلك في الجزء الثاني. قبل الانتقال إلى ذلك، دعني أشرح لك كيفية إنهاء جلسة.

إنهاء الجلسة

قد تنتهي الجلسة الشاملة لعدة أسباب، بما في ذلك إنهاء الجلس من خلال الرمز البرمجي الخاص بك من خلال طلب إلى XRSession.end(). تشمل الأسباب الأخرى فصل سماعة الرأس أو تطبيق آخر يتحكم فيها. لهذا السبب، يجب أن يراقب التطبيق المُمتثل الحدث end. عند حدوث ذلك، يجب تجاهل الجلسة وعناصر العرض المرتبطة بها. لا يمكن مجددًا استئناف جلسة الواقع الافتراضي الشاملة التي انتهت. لإعادة الدخول إلى التجربة الشاملة، يجب أن يبدأ تطبيقي جلسة جديدة.

تذكَّر من مقالة دخول جلسة أنّني أضفت أثناء الإعداد معالج حدث onend.

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

داخل معالج الأحداث، يمكنك استعادة حالة التطبيق قبل دخول المستخدم إلى الجلسة.

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

الخاتمة

لم أشرح كل ما تحتاجه لكتابة تطبيق Web XR أو تطبيق الواقع المعزّز. نأمل أن نكون قد قدّمنا لك معلومات كافية لفهم الرمز بنفسك، وكافيًا لبدء إجراء التجارب. في المقالة التالية، سأشرح حلقة الإطار ، وهي المكان الذي يتم فيه عرض المحتوى على الشاشة.

صورة من موقع JESHOOTS.COM على Unsplash