الواقع المعزّز: قد تكون على عِلم به

إذا كنت قد استخدمت WebXR Device API من قبل، فأنت على وشك تحقيق ذلك.

Joe Medley
Joe Medley

تم طرح WebXR Device API في الإصدار 79 من Chrome في الخريف الماضي. وكما ذكرنا آنذاك، لا يزال تنفيذ واجهة برمجة التطبيقات في Chrome قيد التطوير. يسرّ فريق Chrome الإعلان عن اكتمال بعض الأعمال. في الإصدار 81 من Chrome، تم طرح ميزتَين جديدتَين:

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

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

قبل الاطّلاع على الرمز، يجب استخدام نموذج جلسة الواقع المعزّز الشاملة مرة واحدة على الأقل. يجب أن يكون لديك هاتف Android حديث يعمل بإصدار Chrome 81 أو إصدار أحدث.

ما هي فائدة ذلك؟

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

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

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

طلب جلسة

طلب جلسة يشبه إلى حد كبير ما رأيته من قبل. عليك أولاً معرفة ما إذا كان نوع الجلسة المطلوب متاحًا على الجهاز الحالي من خلال الاتصال بالرقم xr.isSessionSupported(). بدلاً من طلب 'immersive-vr' كما في السابق، اطلب 'immersive-ar'.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-ar');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter AR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

وكما في السابق، يؤدي ذلك إلى تفعيل زر "بدء الواقع المعزّز". عندما ينقر المستخدم على الزر، يتم استدعاء xr.requestSession() مع تمرير 'immersive-ar' أيضًا.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-ar')
    .then((session) => {
      xrSession = session;
      xrSession.isImmersive = true;
      xrButton.textContent = 'Exit AR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

فندق صغير

ربما لاحظت أنني أبرزت سطرين في آخر عينة من التعليمات البرمجية. يبدو أنّ عنصر XRSession يحتوي على سمة باسم isImmersive. هذه خاصية مساعدة أنشأتها بنفسي، وليست جزءًا من المواصفات. سأستخدمها لاحقًا لاتخاذ قرارات بشأن المحتوى الذي أعرضه للمشاهد. لماذا ليست هذه الخاصية جزءًا من واجهة برمجة التطبيقات؟ لأنّ تطبيقك قد يحتاج إلى تتبُّع هذا السمة بشكل مختلف، قرّر مؤلفو المواصفات إبقاء واجهة برمجة التطبيقات نظيفة.

الدخول إلى جلسة

إليك شكل onSessionStarted() في مقالتي السابقة:

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  gl = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(session, gl)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

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

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  if (session.isImmersive) {
    removeBackground();
  }

  let canvas = document.createElement('canvas');
  gl = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(session, gl)
  });

  refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
  xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
    xrSession.requestAnimationFrame(onXRFrame);
  });

}

المساحات المرجعية

لم تتناول مقالاتي السابقة مساحات الإحالة بشكل مفصّل. يستخدم النموذج الذي أصفه اثنَين منهما، لذا حان الوقت لتصحيح هذا النقص.

تصف المساحة المرجعية العلاقة بين العالم الافتراضي والبيئة المادية للمستخدم. ويتم ذلك من خلال:

  • تحديد أصل نظام الإحداثيات المستخدم للتعبير عن المواضع في العالم الافتراضي.
  • تحديد ما إذا كان من المتوقّع أن يتحرك المستخدم ضمن نظام الإحداثيات هذا
  • ما إذا كان نظام الإحداثيات هذا يحتوي على حدود تمّ تحديدها مسبقًا (لا تستخدم الأمثلة المعروضة هنا أنظمة إحداثيات ذات حدود محددة مسبقًا).

في جميع المساحات المرجعية، يعبّر الإحداثي X عن اليسار واليمين، ويعبّر الإحداثي Y عن الأعلى والأسفل، ويعبّر الإحداثي Z عن الأمام والخلف. القيم الموجبة هي اليسار والفوق والخلف، على التوالي.

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

let refSpaceType
function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  if (session.isImmersive) {
    removeBackground();
  }

  let canvas = document.createElement('canvas');
  gl = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(session, gl)
  });

  refSpaceType = xrSession.isImmersive ? 'local' : 'viewer';
  xrSession.requestReferenceSpace(refSpaceType).then((refSpace) => {
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

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

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

viewer: يتم استخدام هذه المساحة التي تتبع جهاز العرض بشكلٍ متكرّر للمحتوى المعروض مضمّنًا في الصفحة. عند تمريرها إلى getViewerPose، لا يوفّر العارض أيّ تتبّع، وبالتالي يُبلغ دائمًا عن وضع في الأصل ما لم يعدّله التطبيق باستخدام XRReferenceSpace.getOffsetReferenceSpace(). يستخدم المثال هذا لتفعيل ميزة تمويه الخلفية بالكاميرا باللمس.

تشغيل تكرار إطار

من الناحية النظرية، لن يحدث أي تغيير في الخطوات التي اتّبعتها في جلسة الواقع الافتراضي الموضّحة في مقالاتي السابقة. مرِّر نوع المساحة المرجعية إلى XRFrame.getViewerPose(). سيكون الرمز XRViewerPose المعروض من النوع الحالي لمساحة المرجع. يتيح استخدام القيمة viewer التلقائية للصفحة عرض معاينات المحتوى قبل طلب موافقة المستخدم على استخدام الواقع المعزّز أو الواقع الافتراضي. يوضّح ذلك نقطة مهمة: يستخدم المحتوى المضمّن حلقة عرض الإطارات نفسها المستخدَمة في المحتوى الغامر، ما يقلل من مقدار الرمز البرمجي الذي يجب الاحتفاظ به.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  let xrViewerPose = xrFrame.getViewerPose(refSpaceType);
  if (xrViewerPose) {
    // Render based on the pose.
  }
}

الخاتمة

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

صورة من تصوير ديفيد جراندموجين على موقع Unسباش