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

إذا كنت قد استخدمت WebXR Device API من قبل، فسينتهي بك الأمر إلى ذلك.

Joe Medley
Joe Medley

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

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

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

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

ما فائدته؟

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

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

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

وكما حدث سابقًا، يؤدي هذا إلى تفعيل زر "Enter AR". عندما ينقر المستخدم عليه، اتصل بـ 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() على نوع المساحة المرجعية المطلوب. المزيد عن ذلك عندما نصل إلى حلقة الإطار. نحتاج في الوقت الحالي إلى اختيار نوع مرجعي مناسب للواقع المعزز. مرة أخرى، هذا يستخدم خاصية الملاءمة الخاصة بي.

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 للحصول على المزيد من المقالات في العام القادم.

تصوير David Grandmougin على موقع UnLaunch