תחילת העבודה עם Three.js

מבוא

השתמשתי ב-Three.js בחלק מהניסויים שלי, והוא עושה עבודה נהדרת בהסרת הבעיות שמתעוררות כשמתחילים לעבוד עם תלת-ממד בדפדפן. בעזרתו אפשר ליצור מצלמות, אובייקטים, תאורה, חומרים ועוד, ויש לכם אפשרות לבחור מנוע עיבוד גרפי (renderer), כלומר אתם יכולים להחליט אם הסצנה תתואר באמצעות לוח הציור של HTML 5, WebGL או SVG. וכיוון שמדובר בקוד פתוח, אפשר גם להשתתף בפרויקט. אבל כרגע אתמקד במה שלמדתי כששיחקתי איתו כמנוע, ואסביר על כמה מהיסודות.

למרות כל היתרונות של Three.js, יכול להיות שתתקלו בבעיות. בדרך כלל תצטרכו להקדיש זמן רב למקרים לדוגמה, להנדסה הפוכה (במקרה שלי בהחלט) ולחיפוש פונקציונליות ספציפית, ולפעמים לשאול שאלות ב-GitHub. דרך אגב, אם יש לך שאלות, גיליתי שMr. doob ו-AlteredQualia עוזרים מאוד.

1. העקרונות הבסיסיים

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

בעולם התלת-ממדי שלנו יהיו כמה מהאלמנטים הבאים, ואני אעזור לכם ליצור אותם:

  1. סצנה
  2. כלי לעיבוד/יצירת תמונה ממוחשבת
  3. מצלמה
  4. אובייקט אחד או שניים (עם חומרי גלם)

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

2. תמיכה

רק הערה קצרה לגבי התמיכה בדפדפנים. לדעתי, דפדפן Chrome של Google הוא הדפדפן הטוב ביותר לעבודה, מבחינת האפשרויות של מנועי העיבוד הנתמכים והמהירות של מנוע JavaScript הבסיסי. Chrome תומך ב-Canvas, ב-WebGL וב-SVG, והוא מהיר במיוחד. דפדפן Firefox מדורג במקום השני, עם הגרסה החדשה 4. מנוע ה-JavaScript שלו נראה איטי יותר מזה של Chrome, אבל גם כאן התמיכה בטכנולוגיות הרינדור מצוינת. התמיכה ב-WebGL בדפדפנים Opera ו-Safari נמצאת בתהליך הוספה, אבל הגרסאות הנוכחיות שלהם תומכות רק ב-canvas. Internet Explorer (גרסה 9 ואילך) תומך רק ברינדור של קנבס, ולא שמעתי על תוכנית של Microsoft להוסיף יכולות WebGL.

3. הגדרת הסצנה

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

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

אחרי שאמרנו את זה, ובתנאי שהורדתם את three.js והוספתם אותה לקובץ ה-HTML, איך מגדירים סצנה? כך:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

זה לא ממש מסובך.

4. יצירת רשת

אז יש לנו סצנה, מצלמה ומעבד גרפיקה (בקוד לדוגמה בחרתי ב-WebGL), אבל אין לנו מה לצייר. ב-Three.js יש תמיכה בחיבור של כמה סוגי קבצים רגילים, וזה מצוין אם אתם מייצאים מודלים מ-Blender, ‏ Maya, ‏ Cinema4D או מכל תוכנה אחרת. כדי לשמור על פשטות (הרי המטרה היא להתחיל!), אדבר על פרימיטיבים. פריימים הם רשתות גיאומטריות, פריימים בסיסיים יחסית כמו כדורים, מישורים, קוביות וצילינדרים. באמצעות Three.js אפשר ליצור בקלות את סוגי הפרימיטיבים הבאים:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

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

5. חומרים

ללא ספק, זהו אחד החלקים השימושיים ביותר ב-Three.js. הוא מספק מספר חומרים נפוצים (ושימושיים מאוד) שאפשר להחיל על המרקמים:

  1. 'בסיסי' – כלומר, המערכת פשוט תיצור עיבוד 'ללא תאורה'.
  2. Lambert
  3. Phong

יש עוד, אבל שוב, מטעמי פשטות, אשאיר לך לגלות אותם בעצמך. במיוחד ב-WebGL, החומרים האלה יכולים להיות מצילי חיים. למה? כי ב-WebGL צריך לכתוב שידורים (shaders) לכל מה שמרינדרים. שפות שדרוג (shaders) הן נושא עצום בפני עצמו, אבל בקצרה, הן נכתבות ב-GLSL (שפת שדרוג של OpenGL), שמספרת ל-GPU איך משהו אמור להיראות. כלומר, צריך לחקות את המתמטיקה של התאורה, ההשתקפות וכו'. זה יכול להפוך למורכב מאוד במהירות. בזכות Three.js, אתם לא צריכים לעשות את זה אם אתם לא רוצים, כי הספרייה מטפלת בזה בשבילכם. עם זאת, אם רוצים לכתוב שגיאות, אפשר לעשות זאת גם באמצעות MeshShaderMaterial, כך שההגדרה גמישה.

בינתיים, נחייב חומר Lambert על הכדור:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

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

6. להדליק אורות!

אם תבצעו עיבוד של הסצנה עכשיו, יופיע עיגול אדום. למרות שהחלנו חומר Lambert, אין תאורה בסצנה, ולכן כברירת מחדל, Three.js יחזור לתאורה סביבתית מלאה, שהיא זהה לצביעה רגילה. נתקן את זה באמצעות נקודת אור פשוטה:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. עיבוד

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

// draw!
renderer.render(scene, camera);

עם זאת, סביר להניח שתרצו לבצע עיבוד (render) יותר מפעם אחת, כך שאם אתם מתכננים לבצע לולאה, מומלץ להשתמש ב-requestAnimationFrame. זוהי ללא ספק הדרך החכמה ביותר לטפל באנימציה בדפדפן. עדיין אין תמיכה מלאה ב-shim, לכן מומלץ מאוד לעיין בshim של Paul Irish.

8. מאפייני אובייקט נפוצים

אם תעיינו בקוד של Three.js, תראו שרבים מהאובייקטים 'יורשים' מ-Object3D. זהו אובייקט בסיס שמכיל כמה מאפיינים שימושיים מאוד, כמו פרטי המיקום, הסיבוב והגודל. באופן ספציפי, ה-Sphere שלנו הוא Mesh שעובר בירושה מ-Object3D, ונוספים לו המאפיינים שלו: גיאומטריה וחומרים. למה הזכרתי את הדברים האלה? סביר להניח שלא תרצו פשוט להציג כדור במסך שלא עושה כלום, ולכן כדאי לבדוק את המאפיינים האלה כי הם מאפשרים לשנות את הפרטים הבסיסיים של המרקמים והמערכות בזמן אמת.

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. Dirty Little Secrets

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

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

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

סיכום

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