האינטרנט העשיר הוא חוויה של עולם וירטואלי שמתארח בדפדפן. כל חוויות המציאות המדומה האלה מופיעות בדפדפן או במשקפי מציאות מדומה.
האינטרנט העשיר הוא חוויה של עולם וירטואלי שמתארח בדפדפן. ההגבלה הזו חלה על חוויות מציאות מדומה (VR) מלאות שמוצגות בדפדפן או במשקפי VR, כמו Daydream של Google, Oculus Rift, Samsung Gear VR, HTC Vive ו-Windows Mixed Reality Headsets, וגם על חוויות של מציאות רבודה שפותחו למכשירים ניידים עם תמיכה ב-AR.
אנחנו משתמשים בשני מונחים כדי לתאר חוויות immersive, אבל צריך להתייחס אליהם כאל ספקטרום שנע מהמציאות המלאה לסביבת VR immersive מלאה, עם רמות שונות של AR באמצע.
דוגמאות לחוויות סוחפות:
- סרטונים סוחפים ב-360°
- סרטונים מסורתיים בפורמט 2D (או 3D) שמוצגים בסביבה סוחפת
- תצוגות חזותיות של נתונים
- שופינג מהבית
- אומנות
- משהו מגניב שאף אחד עדיין לא חשב עליו
איך מגיעים לשם?
האינטרנט הסוחף זמין כבר כמעט שנה, אבל עדיין בשלב מוקדם. עשינו זאת באמצעות WebVR 1.1 API, שהיה זמין בגרסת מקור לניסיון מ-Chrome 62. ה-API הזה נתמך גם ב-Firefox וב-Edge, וגם ב-polyfill ל-Safari.
אבל הגיע הזמן להתקדם.
תקופת הניסיון של גרסת המקור הסתיימה ב-24 ביולי 2018, והמפרט הוחלף ב-WebXR Device API ובגרסת מקור חדשה לניסיון.
מה קרה ל-WebVR 1.1?
למדנו הרבה מ-WebVR 1.1, אבל עם הזמן התברר שצריך לבצע כמה שינויים משמעותיים כדי לתמוך בסוגי האפליקציות שמפתחים רוצים ליצור. רשימת הלקחים המלאה ארוכה מדי כדי לפרט אותה כאן, אבל היא כוללת בעיות כמו העובדה שה-API קשור באופן מפורש לשרשור הראשי של JavaScript, יותר מדי הזדמנויות למפתחים להגדיר הגדרות שגויות באופן מובהק, ושימושים נפוצים כמו חלון קסם שהוא תופעת לוואי ולא תכונה מכוונת. (חלון קסם הוא טכניקה לצפייה בתוכן immersive בלי אוזניות, שבה האפליקציה יוצרת תצוגה אחת על סמך חיישן הכיוון של המכשיר).
העיצוב החדש מאפשר הטמעות פשוטות יותר ושיפורי ביצועים משמעותיים. במקביל, גם התחילו להשתמש ב-AR ובתרחישים אחרים לדוגמה, והיה חשוב לנו שתהיה אפשרות להרחיב את ה-API כדי לתמוך בהם בעתיד.
ה-WebXR Device API תוכנן ונלקח שם בהתאם לתרחישי השימוש המורחבים האלה, והוא מספק נתיב טוב יותר להמשך התהליך. מפתחים שמטמיעים את WebVR התחייבו לעבור ל-WebXR Device API.
מהו WebXR Device API?
בדומה למפרט WebVR שקדמו לו, WebXR Device API הוא תוצר של קבוצת הקהילה של האינטרנט העשיר, שכוללת שותפים מ-Google, מ-Microsoft, מ-Mozilla ועוד. ה-'X' ב-XR הוא סוג של משתנה אלגברי שמייצג כל דבר בספקטרום של חוויות immersive. הוא זמין בגרסת הניסיון למקור שצוינה קודם, וגם באמצעות polyfill.
כשהמאמר הזה פורסם במקור בתקופת הבטא של Chrome 67, הופעלו רק יכולות של VR. מציאות רבודה הגיעה ל-Chrome 69. מידע נוסף זמין במאמר מציאות רבודה לאינטרנט.
יש הרבה יותר ל-API החדש הזה ממה שאוכל להסביר במאמר כזה. אני רוצה לתת לכם מספיק מידע כדי שתוכלו להתחיל להבין את הדוגמאות ל-WebXR. מידע נוסף זמין בהסרטון המקורי ובמדריך למשתמשי 'אינטרנט immersive' מוקדמים. ארחיב את הגרסה השנייה עם התקדמות תקופת הניסיון. אפשר לפתוח בעיות או לשלוח בקשות משיכה.
במאמר הזה אסביר איך מתחילים, מפסיקים ומפעילים סשן XR, וגם אציג כמה עקרונות בסיסיים לגבי עיבוד קלט.
לא אדבר על ציור תוכן AR/VR במסך. ממשק ה-API של מכשיר WebXR לא מספק תכונות של רינדור תמונות. זה תלוי בך. הציור מתבצע באמצעות ממשקי WebGL API. אפשר לעשות את זה אם ממש שאפתנים. עם זאת, מומלץ להשתמש במסגרת. בדוגמאות האינטרנט של חוויית הצפייה העמוקה נעשה שימוש באתר שנוצר במיוחד לדמואים, שנקרא Cottontail. Three.js תומך ב-WebXR מאז מאי. לא שמעתי כלום על A-Frame.
הפעלה של אפליקציה והרצה שלה
התהליך הבסיסי הוא:
- מבקשים מכשיר XR.
- אם האפשרות זמינה, אפשר לבקש סשן XR. אם רוצים שהמשתמש ישים את הטלפון באוזניות, מדובר בסשן immersive (מרתק) שדורש מחווה מהמשתמש כדי להיכנס אליו.
- משתמשים בסשן כדי להריץ לולאת רינדור שמספקת 60 פריימים של תמונות לשנייה. ציירו תוכן מתאים למסך בכל פריים.
- מריצים את לולאת הרינדור עד שהמשתמש מחליט לצאת.
- מסיימים את הסשן של XR.
נבדוק את הנושא לעומק ונכלול קוד. לא תהיה לך אפשרות להריץ אפליקציה מהמידע שאני עומד להראות לך. אבל שוב, זה רק כדי לתת מושג.
בקשה למכשיר XR
כאן תזהו את קוד זיהוי התכונות הרגיל. אפשר להכין פונקציה בשם כלשהו, למשל checkForXR()
, שתעטוף את הקוד הזה.
אם אתם לא משתמשים בסשן immersive, אתם יכולים לדלג על פרסום הפונקציונליות ועל קבלת תנועת משתמש, ולעבור ישירות לבקשת סשן. סשן immersive הוא סשן שבו נדרש שימוש באוזניות. סשן לא סוחף פשוט מראה את התוכן במסך המכשיר. רוב האנשים חושבים על המציאות המדומה כשמדברים על מציאות מדומה או על מציאות רבודה. האפשרות הזו נקראת לפעמים 'חלון קסם'.
if (navigator.xr) {
navigator.xr.requestDevice()
.then(xrDevice => {
// Advertise the AR/VR functionality to get a user gesture.
})
.catch(err => {
if (err.name === 'NotFoundError') {
// No XRDevices available.
console.error('No XR devices available:', err);
} else {
// An error occurred while requesting an XRDevice.
console.error('Requesting XR device failed:', err);
}
})
} else{
console.log("This browser does not support the WebXR API.");
}
שליחת בקשה לסשן XR
עכשיו, אחרי שהמכשיר והמחווה של המשתמש מוכנים, הגיע הזמן לקבל סשן. כדי ליצור סשן, הדפדפן צריך לוח ציור שבו אפשר לצייר.
xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
// The immersive option is optional for non-immersive sessions; the value
// defaults to false.
immersive: false,
outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Use a WebGL context as a base layer.
xrSession.baseLayer = new XRWebGLLayer(session, gl);
// Start the render loop
})
הרצת לולאת הרינדור
הקוד של השלב הזה קצת מסובך. כדי להסביר את זה, אשתמש בהרבה מילים. אם אתם רוצים לראות את הקוד הסופי, תוכלו לעיין בו במהירות ואז לחזור להסבר המלא. יש הרבה דברים שאולי לא תוכלו להסיק.
התהליך הבסיסי של לולאת רינדור הוא:
- שולחים בקשה לפריים אנימציה.
- שולחים שאילתה לגבי המיקום של המכשיר.
- הצגת תוכן במיקום של המכשיר על סמך המיקום שלו.
- מבצעים את הפעולות הנדרשות למכשירי הקלט.
- חוזרים 60 פעמים בשנייה, עד שהמשתמש מחליט לצאת.
שליחת בקשה לפריים של הצגה
למילה 'פריים' יש כמה משמעויות בהקשר של WebXR. הראשון הוא מסגרת העזר שמגדירה את המיקום שממנו מחושב המקור של מערכת הקואורדינטות, ואת מה שקורה למקור הזה כשהמכשיר זז. (האם התצוגה נשארת זהה כשהמשתמש זז או משתנה כפי שהיא הייתה במציאות?)
הסוג השני של מסגרת הוא מסגרת הצגה, שמיוצגת על ידי אובייקט XRFrame
. האובייקט הזה מכיל את המידע הנדרש כדי להציג במכשיר פריים יחיד של סצנה ב-AR/VR. זה קצת מבלבל כי מסגרת של הצגה מאוחזרת באמצעות קריאה ל-requestAnimationFrame()
.
כך הוא תואם ל-window.requestAnimationFrame()
.
לפני שאמשיך, אציג לך קוד. בדוגמה הבאה מוסבר איך מפעילים את לולאת הרינדור ואיך שומרים עליה. שימו לב לשימוש הכפול במילה frame. שימו לב לקריאה הרקורסיבית ל-requestAnimationFrame()
. הפונקציה הזו תופעל 60 פעמים בשנייה.
xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
// The time argument is for future use and not implemented at this time.
// Process the frame.
xrFrame.session.requestAnimationFrame(onFrame);
}
});
תנוחות
לפני שאפשר לצייר משהו במסך, צריך לדעת לאן מכשיר התצוגה מכוון וצריכה להיות לכם גישה למסך. באופן כללי, המיקום והכיוון של אובייקט ב-AR/VR נקראים 'תנוחה'. גם לצופים וגם למכשירי הקלט יש תנוחה. (אדבר על ציוד קלט בהמשך). גם תנוחת הצופה וגם תנוחת מכשיר הקלט מוגדרות כמטריצה 4 על 4 שמאוחסנת ב-Float32Array
בסדר עמודות ראשי. כדי לקבל את תנוחת הצופה, צריך להפעיל את הפונקציה XRFrame.getDevicePose()
על אובייקט המסגרת הנוכחי של האנימציה.
תמיד כדאי לבדוק אם קיבלתם חזרה את תנוחת היד. אם משהו השתבש, לא רוצים לצייר על המסך.
let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
// Draw something to the screen.
}
צפיות
אחרי שבודקים את התנוחה, הגיע הזמן לצייר משהו. האובייקט שאליו משרטטים נקרא תצוגה (XRView
). כאן יש חשיבות לסוג הסשן. התצוגות מאוחזרות מהאובייקט XRFrame
כמערך. אם נמצאים בסשן לא סוחף, למערך יש תצוגה אחת. אם אתם משתמשים בסשן immersive, המערך מכיל שני רכיבים, אחד לכל עין.
for (let view of xrFrame.views) {
// Draw something to the screen.
}
זהו הבדל חשוב בין WebXR לבין מערכות אחרות של חוויה immersive. אולי נראה שאין טעם לבצע חזרה על תצוגה אחת, אבל כך תוכלו ליצור נתיב עיבוד אחד למגוון מכשירים.
כל לולאת הרינדור
אם אשלב את כל המידע הזה, אקבל את הקוד שבהמשך. השארתי placeholder למכשירי הקלט, שעליו ארחיב בהמשך.
xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
// The time argument is for future use and not implemented at this time.
let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
for (let view of xrFrame.views) {
// Draw something to the screen.
}
}
// Input device code will go here.
frame.session.requestAnimationFrame(onFrame);
}
}
סיום הסשן ב-XR
סשן XR יכול להסתיים מכמה סיבות, כולל סיום על ידי הקוד שלכם באמצעות קריאה ל-XRSession.end()
. סיבות אחרות יכולות להיות שהאוזניות לא מחוברות או שאפליקציה אחרת מפעילה אותן. לכן, באפליקציה תקינה צריך לעקוב אחרי אירוע הסיום, וכשהוא מתרחש, צריך להשליך את אובייקטי הסשן והעיבוד. אי אפשר להמשיך סשן XR אחרי שהוא מסתיים.
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Create a WebGL layer and initialize the render loop.
xrSession.addEventListener('end', onSessionEnd);
});
// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
xrSession = null;
// Ending the session stops executing callbacks passed to the XRSession's
// requestAnimationFrame(). To continue rendering, use the window's
// requestAnimationFrame() function.
window.requestAnimationFrame(onDrawFrame);
}
איך פועלת האינטראקציה?
כמו בכל משך החיים של האפליקציה, אני רוצה לתת לכם הצצה לאינטראקציה עם אובייקטים ב-AR או ב-VR.
WebXR Device API מיישמים גישת 'הצבעה ולחיצה' לקלט של משתמשים. בגישה הזו, לכל מקור קלט יש קרן של סמן מוגדרת שמציינת לאן מכשיר הקלט מצביע, ואירועים שמציינים מתי משהו נבחר.
האפליקציה מצייר את קרן הסמן ומראה לאן היא מצביעה. כשהמשתמש לוחץ על המכשיר לקליטת נתונים, האירועים מופעלים – select
, selectStart
ו-selectEnd
, באופן ספציפי. האפליקציה קובעת על מה לחצו ומגיבה בהתאם.
מכשיר הקלט וקרן הסמן
למשתמשים, קרן הסמן היא רק קו חלש בין הבקר לבין מה שהם מצביעים עליו. אבל האפליקציה שלכם צריכה לצייר אותה. כלומר, צריך לקבל את תנוחת מכשיר הקלט ולצייר קו מהמיקום שלו לאובייקט במרחב ה-AR/VR. התהליך הזה נראה בערך כך:
let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
if (!inputPose) {
continue;
}
if (inputPose.gripMatrix) {
// Render a virtual version of the input device
// at the correct position and orientation.
}
if (inputPose.pointerMatrix) {
// Draw a ray from the gripMatrix to the pointerMatrix.
}
}
זוהי גרסה עדכנית של הדוגמה למעקב אחר קלט מקבוצת הקהילה של Immersive Web. בדומה לעיבוד פריים, תוכלו לשרטט את קרן ההצבעה והמכשיר תלוי בכם. כמו שציינו קודם, הקוד הזה חייב להיות מופעל כחלק מלולאת העיבוד.
בחירת פריטים במרחב הווירטואלי
פשוט להצביע על דברים ב-AR/VR זה די חסר תועלת. כדי לבצע פעולות מועילות, המשתמשים צריכים להיות מסוגלים לבחור דברים. WebXR Device API מספק שלושה אירועים בתגובה לאינטראקציות של משתמשים: select
, selectStart
ו-selectEnd
. יש להם תכונה לא צפויה: הם רק מדווחים על לחיצה על מכשיר קלט. הן לא מאפשרות לדעת על איזה פריט בסביבה לחצו. פונקציות טיפול באירועים מתווספות לאובייקט XRSession
, וצריך להוסיף אותן ברגע שהן זמינות.
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
// Create a WebGL layer and initialize the render loop.
xrSession.addEventListener('selectstart', onSelectStart);
xrSession.addEventListener('selectend', onSelectEnd);
xrSession.addEventListener('select', onSelect);
});
הקוד הזה מבוסס על דוגמה לבחירת קלט, למקרה שתרצו להבין את ההקשר.
כדי להבין על מה לחצו, אתם צריכים להשתמש בתנוחה. (הפתעת? לא חשבתי כך). הפרטים האלה ספציפיים לאפליקציה או למסגרת שבה אתם משתמשים, ולכן הם לא נכללים במאמר הזה. הגישה של Cottontail מפורטת בדוגמה של בחירת קלט.
function onSelect(ev) {
let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
if (!inputPose) {
return;
}
if (inputPose.pointerMatrix) {
// Figure out what was clicked and respond.
}
}
מסקנות: במבט קדימה
כפי שציינתי קודם, מציאות רבודה צפויה להופיע ב-Chrome 69 (בגרסת Canary מתישהו ביוני 2018). עם זאת, מומלץ לנסות את מה שיש לנו עד עכשיו. אנחנו זקוקים למשוב כדי לשפר אותו. תוכלו לעקוב אחרי ההתקדמות ב-ChromeStatus.com לבדיקת WebXR Hit Test. אפשר גם לעקוב אחרי עוגנים של WebXR כדי לשפר את מעקב התנוחה.