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

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

Joe Medley
Joe Medley

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

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

ما هو الويب المجسَّم؟

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

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

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

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

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

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

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

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

طلب جلسة

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

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

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

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. أربطها باللوحة من خلال استدعاء 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. ارسم شيئًا للمخزن المؤقت للإطارات.

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

طلب معاودة الاتصال XRFrameRequest

أنت الذي تحدِّد السمة 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 أو AR. آمل أن أكون قد أعطيتك ما يكفي لبدء فهم التعليمات البرمجية لنفسك، وما يكفي لبدء التجربة. في المقالة التالية، سأشرح حلقة الإطار، حيث يتم رسم المحتوى على الشاشة.

صورة من JESHOOTS.COM على Un تحقق