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

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

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 ב-Unbounce