מציאות רבודה: ייתכן שכבר אתם יודעים אותה

אם כבר השתמשתם ב-WebXR Device API, כבר כמעט סיימתם.

Joe Medley
Joe Medley

ממשק WebXR Device API שוחרר בסתיו האחרון בגרסת Chrome 79. כפי שציינו אז, ההטמעה של ה-API ב-Chrome נמצאת בשלבי פיתוח. אנחנו ב-Chrome שמחים להודיע שחלק מהעבודה הסתיימה. בגרסה 81 של Chrome נוספו שתי תכונות חדשות:

המאמר הזה עוסק במציאות רבודה. אם כבר השתמשתם ב-WebXR Device API, תוכלו לשמוע שצריך ללמוד מעט מאוד דברים חדשים. הכניסה לסשן WebXR היא דומה במידה רבה. הפעלת לולאת פריים היא בעיקר זהה. ההבדלים נובעים מההגדרות שמאפשרות להציג את התוכן בצורה מתאימה למציאות רבודה. אם אתם לא מכירים את המושגים הבסיסיים של WebXR, כדאי לקרוא את הפוסטים הקודמים שלי על WebXR Device API, או לפחות להכיר את הנושאים שבהם הם עוסקים. צריך לדעת איך לבקש סשן ולהיכנס אליו ואיך להריץ מחזור של פריימים.

מידע נוסף על בדיקת היטים זמין במאמר הנלווה מיקום אובייקטים וירטואליים בתצוגות של העולם האמיתי. הקוד במאמר הזה מבוסס על הדוגמה של סשן AR immersive (דוגמה מקור) מהדוגמאות של WebXR Device API של קבוצת העבודה של האינטרנט העשיר.

לפני שמתעמקים בקוד, כדאי להשתמש בדוגמה לסשן AR immersive לפחות פעם אחת. נדרש טלפון Android מודרני עם Chrome מגרסה 81 ואילך.

למה זה שימושי?

המציאות המדומה תהיה תוספת חשובה להרבה דפי אינטרנט קיימים או חדשים, כי היא תאפשר להטמיע תרחישים לדוגמה של AR בלי לצאת מהדפדפן. לדוגמה, התכונה הזו יכולה לעזור לאנשים ללמוד באתרים חינוכיים, ולאפשר לקונים פוטנציאליים לראות איך פריטים ייראו בבית בזמן הקנייה.

נבחן את תרחיש השימוש השני. נסו לדמיין סימולציה של הצבת ייצוג בגודל טבעי של אובייקט וירטואלי בסצנה אמיתית. אחרי שממקמים את התמונה, היא נשארת על המשטח שנבחר, מוצגת בגודל שבו היא תופיע אם הפריט האמיתי יהיה על המשטח הזה ומאפשרת למשתמש לנוע סביבה, להתקרב אליה או להתרחק ממנה. כך הצופים יכולים להבין טוב יותר את האובייקט מאשר באמצעות תמונה דו-ממדית.

אני מקדימה את עצמי. כדי לבצע את הפעולות שתיארתי, צריך פונקציונליות של AR ואמצעי זיהוי כלשהו של משטחים. המאמר הזה עוסק באפשרות הראשונה. המאמר הנלווה על 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
  }
}

כמו קודם, הלחצן 'כניסה ל-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. זהו מאפיין נוחות שיצרתי בעצמי, והוא לא חלק מהמפרט. אשתמש בו בהמשך כדי לקבל החלטות לגבי התוכן שאציג לצופים. למה המאפיין הזה לא נכלל ב-API? יכול להיות שהאפליקציה שלכם תצטרך לעקוב אחרי המאפיין הזה באופן שונה, ולכן מחברי המפרט החליטו לשמור על ניקיון ה-API.

כניסה לסשן

זכור איך נראה 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() תלויות בסוג מרחב העזר המבוקש. נרחיב על כך בהמשך, כשנגיע ל-frame loop. עכשיו אנחנו צריכים לבחור סוג של קובץ עזר שמתאים למציאות רבודה. שוב, הקוד הזה משתמש במאפיין הנוחות שלי.

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

אם נכנסתם לדוגמה של סשן AR immersive, תבחינו שהסצנה בהתחלה סטטית ולא מופיעה בה בכלל מציאות מוגברת. אפשר לגרור ולהחליק את האצבע כדי לנוע בתוך הסצנה. אם לוחצים על 'הפעלת AR', הרקע נעלם ותוכלו לזוז בתוך הסצנה על ידי הזזת המכשיר. בכל אחד מהמצבים נעשה שימוש בסוגים שונים של מרחבי עזר. הטקסט המודגש למעלה מראה איך האפשרות הזו נבחרת. הוא משתמש בסוגי ההפניות הבאים:

local – המקור נמצא במיקום הצופה בזמן יצירת הסשן. המשמעות היא שלחוויה הזו לא בהכרח יש רף מוגדר, והמיקום המדויק של המקור עשוי להשתנות בהתאם לפלטפורמה. למרות שאין גבולות מוגדרים מראש למרחב, צפוי שתוכלו לצפות בתוכן ללא תנועה מלבד סיבוב. כפי שאפשר לראות בדוגמה שלנו ל-AR, יכול להיות שתוכלו לזוז מעט במרחב.

viewer – משמש בדרך כלל לתוכן שמוצג בשורה בדף. המרחב הזה משתנה בהתאם למכשיר הצפייה. כשהיא מועברת ל-getViewerPose, היא לא מספקת מעקב, ולכן תמיד מדווחת על תנוחה במקור, אלא אם האפליקציה משנה אותה באמצעות XRReferenceSpace.getOffsetReferenceSpace(). הדוגמה משתמשת בכך כדי לאפשר תנועת פנורמה במצלמה באמצעות מגע.

הרצת לולאת מסגרות

מבחינה מושגית, אין שינוי ממה שעשיתי בסשן ה-VR שמתואר במאמרים הקודמים שלי. מעבירים את סוג המרחב המשותף של ההפניה אל XRFrame.getViewerPose(). הערך של XRViewerPose שיוחזר יהיה לפי סוג המרחב המשותף הנוכחי. שימוש ב-viewer כברירת מחדל מאפשר להציג בדף תצוגות מקדימות של תוכן לפני שמבקשים מהמשתמשים להביע הסכמה לשימוש ב-AR או ב-VR. זה ממחיש נקודה חשובה: התוכן שמוטמע בקוד משתמש באותה לולאת מסגרות כמו התוכן האינטראקטיבי, וכך מקטין את כמות הקוד שצריך לתחזק.

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

סיכום

סדרת המאמרים הזו עוסקת רק ביסודות של הטמעת תוכן immersive באינטרנט. דוגמאות ל-WebXR Device API של קבוצת העבודה של האינטרנט העשיר מציגות יכולות ותרחישים לדוגמה רבים נוספים. פרסמנו גם מאמר בנושא בדיקת התאמה שמסביר על ממשק API לזיהוי משטחים והצבת פריטים וירטואליים בתצוגת המצלמה בעולם האמיתי. מומלץ לעיין בהם ולעקוב אחרי הבלוג של web.dev כדי לקבל מאמרים נוספים במהלך השנה הקרובה.

תמונה של David Grandmougin ב-Unsplash