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

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

Joe Medley
Joe Medley

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

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

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

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

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

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

المفاهيم وطريقة الاستخدام

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

تستند الرموز البرمجية الواردة في هذه المقالة إلى نموذج أساسي (الإصدار التجريبي، المصدر) لمجموعة عمل الويب الغامر، ولكنه تم تعديله ليصبح أكثر وضوحًا وبساطة.

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