המציאות הווירטואלית מגיעה לאינטרנט

כמה דברים בסיסיים כדי להכין אתכם למגוון רחב של חוויות סוחפות: מציאות מדומה, מציאות רבודה וכל מה שביניהם.

Joe Medley
Joe Medley

חוויות סוחפות הגיעו לאינטרנט ב-Chrome 79. ה-WebXR Device API מספק חוויית מציאות מדומה שמאפשרת מציאות מדומה, והתמיכה במציאות רבודה זמינה ב-Chrome 81. עדכון ל-GamePad API מרחיב את השימוש המתקדם בפקדים גם ל-VR. בקרוב דפדפנים אחרים יתמכו במפרטים האלה, ביניהם Firefox Reality , Oculus Browser, דפדפן Edge ו-Hellio של Magic Leap.

המאמר הזה מתחיל סדרה בנושא האינטרנט העשיר. בחלק הזה נסביר איך להגדיר אפליקציה בסיסית ב-WebXR, וגם להיכנס לסשן XR ולצאת ממנו. מאמרים מאוחרים יותר יכללו את לולאת הפריימים (תהליך העבודה של WebXR), את הפרטים הספציפיים של מציאות רבודה ואת WebXR Hit Test API, שבעזרתו ניתן לזהות פלטפורמות בסשן AR. אלא אם צוין אחרת, כל מה שדיווחתי עליו ובמאמרים המצליחים חל באופן שווה גם על AR וגם על VR.

מהו האינטרנט העשיר?

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

גרף שממחיש את מגוון החוויות החזותיות, ממציאות מלאה ועד חוויה סוחפת לחלוטין.
מגוון החוויות העשירות והסוחפות

דוגמאות לחוויות סוחפות:

  • משחקים
  • סרטוני וידאו ב-360 מעלות
  • סרטונים מסורתיים בדו-ממד (או בתלת-ממד) שמוצגים בסביבה סוחפת
  • קניית בית
  • הצגת מוצרים בבית לפני שקונים אותם
  • אומנות סוחפת
  • משהו מגניב שאף אחד לא חשב עליו עדיין

מושגים ושימוש

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

הקוד במאמר הזה מבוסס על דוגמת הבאר (הדגמה, מקור) של Immersive Web Work Group, אבל הוא נערך כדי להבהיר את התוכן ולפשט אותו.

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

קביעת פגישה

כדי להיכנס לסשן XR נדרשת תנועת משתמש. כדי לעשות זאת, אפשר להשתמש בתכונה 'זיהוי תכונות' כדי לבדוק את XRSystem (דרך navigator.xr) ולבצע קריאה ל-XRSystem.isSessionSupported(). חשוב לשים לב שבגרסאות 79 ו-80 של Chrome האובייקט XRSystem נקרא XR.

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

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

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

כניסה לסשן

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

גם דרוש לי אלמנט <canvas> כדי לשרטט את הסצנה עליו. הוא צריך להיות WebGLRenderingContext תואם ל-XR או ל-WebGL2RenderingContext. כל השרטוט מתבצע באמצעותם או באמצעות framework מבוססת 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(). כאן מתחילים להציג תוכן וירטואלי, שמתרחש בתוך המסגרת בלולאה.

הפעלה של לולאת מסגרת

לולאת המסגרת היא לולאה אינסופית הנשלטת על ידי סוכן משתמש, שבה התוכן משורטט שוב ושוב למסך. התוכן משורטט בבלוקים נפרדים שנקראים 'מסגרות'. רצף הפריימים יוצר אשליה של תנועה. באפליקציות VR, קצב הפריימים לשנייה יכול להיות בין 60 ל-144. AR ל-Android פועל במהירות של 30 FPS. הקוד לא אמור להניח קצב פריימים מסוים.

התהליך הבסיסי של לולאת המסגרת הוא:

  1. התקשרו אל XRSession.requestAnimationFrame(). בתגובה, סוכן המשתמש מפעיל את XRFrameRequestCallback, שמוגדר על ידך.
  2. בתוך פונקציית הקריאה החוזרת:
    1. להתקשר שוב אל XRSession.requestAnimationFrame().
    2. נותנים לצופה את התנוחה.
    3. מעבירים ('קישור') WebGLFramebuffer מה-XRWebGLLayer אל WebGLRenderingContext.
    4. חוזרים על כל אובייקט XRView, מאחזרים את ה-XRViewport שלו מה-XRWebGLLayer ומעבירים אותו ל-WebGLRenderingContext.
    5. צייר משהו למאגר המסגרות.

בהמשך המאמר הזה מתוארים שלב 1 וחלק משלב 2, ההגדרה וקריאה של ה-XRFrameRequestCallback. שאר הפריטים בשלב 2 מפורטים בחלק 2.

XRFrameRequestCallback

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