האינטרנט העשיר הוא חוויה של עולם וירטואלי שמתארח בדפדפן. כל חוויות המציאות המדומה האלה מופיעות בדפדפן או במשקפי מציאות מדומה.
האינטרנט העשיר הוא חוויה של עולם וירטואלי שמתארח בדפדפן. ההגדרה הזו כוללת חוויות מציאות מדומה (VR) מלאות שמוצגות בדפדפן או במשקפי VR כמו Daydream של Google, Oculus Rift, Samsung Gear VR, HTC Vive ו-Windows Mixed Reality Headsets, וגם חוויות של מציאות רבודה שפותחו למכשירים ניידים עם תמיכה ב-AR.
אנחנו משתמשים בשני מונחים כדי לתאר חוויות immersive, אבל צריך להתייחס אליהם כאל ספקטרום שנע מהמציאות המלאה לסביבת VR immersive מלאה, עם רמות שונות של AR באמצע.
דוגמאות לחוויות סוחפות:
- סרטוני וידאו ב-360 מעלות
- סרטונים דו-ממדיים (או תלת-ממדיים) מסורתיים שמוגשים בסביבה סוחפת
- תצוגות חזותיות של נתונים
- שופינג מהבית
- אומנות
- משהו מגניב שאף אחד עדיין לא חשב עליו
איך מגיעים לשם?
האינטרנט הסוחף זמין כבר כמעט שנה, אבל עדיין בשלב מוקדם. עשינו זאת באמצעות 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 פעמים בשנייה עד שהמשתמש מחליט לצאת.
שליחת בקשה לפריים של הצגה
למילה 'פריים' יש כמה משמעויות בהקשר של Web XR. הראשון הוא מסגרת העזר שמגדירה את המיקום שממנו מחושב המקור של מערכת הקואורדינטות, ואת מה שקורה למקור הזה כשהמכשיר זז. (האם התצוגה נשארת זהה כשהמשתמש זז או שהיא משתנה כמו בחיים האמיתיים?)
הסוג השני של מסגרת הוא מסגרת הצגה, שמיוצגת על ידי אובייקט 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.
}
}
זוהי גרסה פשוטה של הדוגמה למעקב אחר קלט מקבוצת הקהילה של האינטרנט העשיר. כמו עיבוד המסגרות, אתם יכולים לבחור אם לצייר את קרן הסמן ואת המכשיר. כפי שצוין קודם, צריך להריץ את הקוד הזה כחלק ממחזור הרינדור.
בחירת פריטים במרחב הווירטואלי
פשוט להצביע על דברים ב-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. אפשר גם לעקוב אחרי עוגנים של WebXR כדי לשפר את מעקב התנוחה.