רינדור טקסט ב-WebVR

בטווח הפרטים

הצגת האתר

בתוך (https://with.in/) יש פלטפורמה לסיפורים במציאות מדומה. לכן, כשהצוות שמע על WebVR ב-2015, מיד התעניינו בפוטנציאל שלו. כיום, תחומי העניין האלה מוצגים לתת-דומיין ייחודי של פלטפורמת האינטרנט שלנו, https://vr.with.in/. כל מי שיש לו דפדפן שתומך ב-VR יכול להיכנס לאתר, ללחוץ על לחצן ולהרכיב אוזניות כדי להיסחף באוסף סרטי ה-VR שלנו.

כיום זה כולל, בין היתר, את Chrome ב-Daydream View. למידע על המכשיר שלכם ועל מסך התושבת על הראש, אפשר לבקר בכתובת https://webvr.info/.

בדומה לסביבות עיבוד אחרות ספציפיות למציאות מדומה, האינטרנט מסתמך בעיקר על ייצוג תלת-ממדי של סצנה. בסצנה הזו יש מצלמה, נקודת המבט שלכם ומספר אובייקטים. כדי לנהל את הסצנה, המצלמה והאובייקטים, אנחנו משתמשים בספרייה בשם Three.js שמשתמשת ברכיב <canvas> כדי לבצע עיבוד ל-GPU של המחשב. יש הרבה תוספי Three.js שימושיים שמאפשרים להציג את הסצנה ב-WebVR. שתי הפלטפורמות העיקריות הן THREE.VREffect ליצירת אזור תצוגה לכל עין ו-THREE.VRControls לתרגום הפרספקטיבה (למשל הסיבוב והמיקום של המסך על תושבת הראש) בצורה משכנעת לסצנה. יש הרבה דוגמאות לאיך ליישם את זה. כדאי לעיין בדוגמאות של Three.js WebVR כדי להתחיל בעבודה.

ככל שהתחלנו לחקור את השימוש ב-WebVR, נתקלנו בבעיה. אם אנחנו מסתכלים על התוכן של האינטרנט, הטקסט הוא חלק בלתי נפרד ממנו. למרות שרוב התוכן שלנו מבוסס על סרטונים, אם עוברים לקטע בתוך האתר, הטקסט מקיף את התוכן, ממשק המשתמש והמידע הנוסף על סרט או סרטים קשורים עשויים לכלול טקסט. בנוסף, כל הטקסט הזה נוצר ב-DOM. כל הניתוחים של WebVR ו-https://vr.with.in/ נמצאים ב-<canvas>.

הטקסט שמשמש ב-WebVR הטקסט שמשמש ב-WebVR
הטקסט שמופיע ב-WebVR עבור vr.with.in

מה האפשרויות שלי?

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

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

ההחלטה שלנו: גופן מפת הסיביות של SDF

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

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

גופן לתהליך עבודה של מפת סיביות של SDF
גופן לתהליך העבודה של מפת הסיביות של SDF

בגופנים של Bitmap יש ריבוע אחד (שני משולשים) לכל תו, ולכן יש בהם פחות גיאומטריה וביצועים טובים יותר מוקטורים משולשים. הם עדיין מבוססים על רשת נקודות כי הם משתמשים בשילוב של מפת מרקם, אבל בעזרת גוון של SDF הם בעצם לא תלויים ברזולוציה, כך שהם נראים יפים יותר ממרקם של בד דו-ממדי. Matt DesLauriers ב-3-bmfont-text כולל גם תכונות טיפוגרפיות אמינות לעטיפת טקסט, לריווח בין אותיות, לגובה שורות וליישור. הגלישה לא נחתכת, כי גודל הגופן נקבע על ידי קנה המידה שלו. בחרנו במסלול הזה כי הוא נתן לנו את האפשרויות הטובות ביותר לעיצוב ושמירה על הביצועים. לצערנו, לא היה קל להטמיע את התכונה הזו, ולכן נמשיך לבצע את השלבים בתקווה לעזור למפתחים אחרים שעובדים ב-WebVR.

1. יצירה של גופן מפת סיביות (bitmap.) ( .png + .fnt)

ממשק Hiero
ממשק Hiero
פלט Hiero (קובץ PNG ב-Bitmap וקובץ .fnt) פלט Hiero (קובץ PNG ב-Bitmap וקובץ .fnt)
פלט Hiero (קובץ PNG ב-Bitmap וקובץ .fnt)

Hiero הוא כלי לאריזת גופנים במפת סיביות (bitmap) שפועל עם Java. במסמכי התיעוד של Hiero לא מוסבר איך להפעיל אותו בלי לעבור תהליך פיתוח מורכב. תחילה, התקינו את Java, אם עדיין לא עשיתם זאת. לאחר מכן, אם לחיצה כפולה על runnable-hiero.jar לא פותחת את Hiero, נסו להריץ אותו באמצעות הפקודה הבאה במסוף:

java -jar runnable-hiero.jar

כאשר Hiero פועל, פותחים גופן שולחן עבודה בפורמט .ttf או .otf, מזינים תווים נוספים שרוצים לכלול, משנים את הרינדור ל-Java כדי להפעיל אפקטים, מגדילים את הגודל כך שהתווים ימלאו את כל כיכר המטמון של הגליף, מוסיפים אפקט של שדה המרחק, מכוונים את קנה המידה של שדה המרחק ומרווחים אותו. ערך קנה המידה הוא כמו רזולוציה. ככל שהיא גבוהה יותר, כך היא תהיה פחות מטושטשת, אבל ככל שייקח ל-Hiro יותר זמן לעבד את התצוגה המקדימה. לאחר מכן שמרו את הגופן של מפת הסיביות. המערכת יוצרת גופן מפת סיביות שמכיל תמונת .png וקובץ תיאור גופן מסוג AngelCode .fnt.

2. המר את AngelCode ל-JSON

עכשיו, לאחר שהגופן של מפת הסיביות נוצר, עלינו לטעון אותו באפליקציית JavaScript באמצעות load-bmfont npm של Matt DesLauriers.

אנחנו יכולים להשתמש ב-load-bmfont ולהשתמש בו בממשק הקצה, אבל במקום זאת מריצים את load-bmfont.js עם ה-Node כדי להמיר ולשמור את קובץ .fnt של Hiero בקובץ.json:

npm install
node load-bmfont.js
דוגמה לפלט JSON
דוגמה לפלט JSON

עכשיו אנחנו יכולים לעקוף את load-bmfont ופשוט לבצע בקשת XHR (XMLHttpRequest) בקובץ הגופן json.

var r = new XMLHttpRequest();
r.open('GET', 'fonts/roboto/bitmap/roboto-bold.json');

r.onreadystatechange = function() {
    if (r.readyState === 4 && r.status === 200) {
    setup(JSON.parse(r.responseText));
    }
};

r.send();

function setup(font) {
    // pass font into TextBitmap object
}

3. טקסט של דפדפן 3Bmfont

אחרי שנטענו את הגופן, הטקסט של מאט מ-3 מילים יטפל בהשארת. מאחר שאנחנו לא משתמשים ב-Node באפליקציה שלנו, אנחנו נעבור browserify שלוש-bmfont-text.js לקובץ three-bmfont-text-bundle.js שניתן להשתמש בו.

npm install -g browserify
browserify three-bmfont-text.js -o three-bmfont-text-bundle.js

4. תוכנת הצללה של SDF

מכווננים את המחוונים afwidth ו-threshold ב-vr.with.in/archive/text-sdf-bitmap/ כדי לראות את ההשפעה של תוכנת ההצללה של שדה המרחק החתום.

5. Usage

לנוחיותכם, יצרתי מחלקה של TextBitmap ל-wrapper עבור טקסט של שלושה bmfonts שהופעל בדפדפן.

Text-sdf-bitmap בפעולה
Text-sdf-bitmap בפעולה
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

יוצרים בקשת XHR לקובץ הגופן עם הסיומת .json ויוצרים אובייקט טקסט בקריאה החוזרת:

var bmtext = new TextBitmap({ options });

כדי לשנות טקסט:

bmtext.text = 'The quick brown fox jumps over the lazy dog.';

scene.add( bmtext.group );
hitBoxes.push( bmtext.hitBox );

קובץ ה- .png של גופן מפת הסיביות נטען עם THREE.TextureLoader ב-text-bitmap.js

TextBitmap כולל גם Hitbox בלתי נראה עבור אינטראקציה של שלושה.js מסוג raycast באמצעות עכבר, מצלמה או בקרי תנועה במעקב ידני, כמו Oculus Touch או בקרי Vive. הגודל של תיבת ההיטים מתעדכן אוטומטית כשמשנים את אפשרויות הטקסט.

הקובץ Bmtext.group נוסף לסצנה 3.js. אם אתם צריכים לגשת לתצוגות של ילדים או של Object3D, תרשים הסצנה של הטקסט ייראה כך:

תרשים של מערכת הקבצים

6. ביטול הקטנה של קובץ JSON ושינוי xoffset

בתוך קובץ GIF של טקסט

אם הקידוד לא פועל, ייתכן שתצטרכו לערוך את ה-xoffset ב-JSON. מדביקים את קובץ ה-JSON ב-Jsbeautifier.org כדי לקבל גרסה לא מוגדרת של הקובץ.

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

קודם כל, צריך להבין לאילו תווים לשייך את מזהה התו ב-JSON. ב-three-bmfont-text-bundle.js, הוסיפו console.log אחרי שורה 240:

    var id = text.charCodeAt(i)
    // console.log(id);

לאחר מכן מקלידים בשדה הטקסט dat.gui בכתובת https://vr.with.in/archive/text-sdf-bitmap/ ובודקים במסוף את המזהה של תו מסוים.

לדוגמה, בגופן מפת הסיביות שלנו, "j" מופיע במיקום רחוק מדי מימין. מזהה התו הוא 106. אז אפשר למצוא את "id": 106 ב-json ולשנות את ה-xoffset שלו מ-1- ל-10.

7. פריסה

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

    * { position: absolute; }

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

פריסת תלת ממד
author.group.position.y = title.group.position.y - title.height - padding;
description.group.position.y = author.group.position.y - author.height - padding;
duration.group.position.y = description.group.position.y - description.height - padding;

ההנחה היא שהמקור המקומי של כל קבוצה TextBitmap מיושר לאורך לחלק העליון של רשת TextBitmap (אפשר להיעזר בעדכון text-bitmap.js). אם משנים את הטקסט באובייקטים האלה מאוחר יותר, והגובה של האובייקט משתנה, צריך גם לחשב מחדש את המיקומים האלה. במקרה הזה, רק מיקום ה-y של הטקסט משתנה, אבל אחת ההזדמנויות לעבודה בתלת-ממד היא היכולת לדחוף ולמשוך את הטקסט בכיוון ה-z, וגם לסובב אותו סביב הצירים x, y ו-z.

סיכום

לטקסט ולפריסה ב-WebVR יש עוד הרבה עבודה לפני שהם קלים לשימוש ולשימוש נרחב כמו HTML ו-CSS. אבל קיימים פתרונות פעילים, ואפשר לעשות ב-WebVR הרבה יותר ממה שאפשר לעשות בדף אינטרנט מסורתי בפורמט HTML. ה-WebVR קיים היום. סביר להניח שמחר יהיו כלים טובים יותר. עד אז, נסו אותה ונסו. פיתוח ללא מסגרת שמופיעה בכל מקום מוביל לפרויקטים ייחודיים יותר, וזה מרגש.