บทนำ
เราใช้ Three.js ในการทดลองบางอย่าง และพบว่าเครื่องมือนี้ช่วยแก้ปัญหาความยุ่งยากในการเริ่มต้นใช้งาน 3 มิติในเบราว์เซอร์ได้ดีมาก ซึ่งคุณสามารถสร้างกล้อง วัตถุ แสง วัสดุ และอื่นๆ ได้ รวมถึงมีตัวเลือกโปรแกรมแสดงผล ซึ่งหมายความว่าคุณจะเลือกได้ว่าต้องการให้วาดฉากโดยใช้ Canvas, WebGL หรือ SVG ของ HTML 5 และเนื่องจากเป็นโอเพนซอร์ส คุณจึงมีส่วนร่วมในโปรเจ็กต์ได้ด้วย แต่ตอนนี้เราจะเน้นไปที่สิ่งที่ได้เรียนรู้จากการใช้งานเป็นเครื่องมือ และอธิบายข้อมูลเบื้องต้นให้คุณฟัง
แม้ว่า Three.js จะยอดเยี่ยมเพียงใด แต่ก็อาจมีปัญหาเกิดขึ้นได้ โดยปกติแล้ว คุณจะต้องใช้เวลากับตัวอย่างต่างๆ การทำวิศวกรรมย้อนกลับ และ (ในกรณีของฉัน) การค้นหาฟังก์ชันการทำงานที่เฉพาะเจาะจง และถามคำถามผ่าน GitHub เป็นครั้งคราว หากมีคำถามเพิ่มเติม เราพบว่า Mr. doob และ AlteredQualia เป็นผู้ให้ความช่วยเหลือที่ยอดเยี่ยมมาก
1. ข้อมูลพื้นฐาน
เราจะถือว่าคุณมีความรู้ด้าน 3 มิติในระดับพอใช้ และมีความเชี่ยวชาญด้าน JavaScript ในเกณฑ์ที่ยอมรับได้ หากไม่ คุณอาจต้องศึกษาข้อมูลสักเล็กน้อยก่อนลองใช้ฟีเจอร์นี้ เนื่องจากอาจทำให้เกิดความสับสนได้
ในโลก 3 มิติของเราจะมีสิ่งต่อไปนี้ ซึ่งเราจะแนะนำคุณเกี่ยวกับขั้นตอนการสร้าง
- ฉาก
- โปรแกรมแสดงผล
- กล้อง
- วัตถุ 1-2 รายการ (พร้อมวัสดุ)
แน่นอนว่าคุณทำสิ่งเจ๋งๆ ได้ และเราหวังว่าคุณจะลองทำสิ่งเหล่านั้นและเริ่มทดลองใช้ 3 มิติในเบราว์เซอร์
2. การสนับสนุน
หมายเหตุสั้นๆ เกี่ยวกับการรองรับในเบราว์เซอร์ จากประสบการณ์ของเรา เบราว์เซอร์ Chrome ของ Google เป็นเบราว์เซอร์ที่ดีที่สุดสำหรับการทำงานในแง่ของโปรแกรมแสดงผลที่รองรับและความเร็วของเครื่องมือ JavaScript พื้นฐาน Chrome รองรับ Canvas, WebGL และ SVG และทำงานได้อย่างรวดเร็ว Firefox ตามมาเป็นอันดับ 2 จากการเปิดตัวเวอร์ชัน 4 ดูเหมือนว่าเครื่องมือนี้จะช้ากว่า Chrome เล็กน้อย แต่การรองรับเทคโนโลยีการแสดงผลนั้นยอดเยี่ยมมาก Opera และ Safari กำลังอยู่ระหว่างการเพิ่มการรองรับ WebGL แต่เวอร์ชันปัจจุบันรองรับเฉพาะ Canvas Internet Explorer (เวอร์ชัน 9 ขึ้นไป) รองรับการแสดงผลแคนวาสเท่านั้น และเราไม่ได้ยินว่า Microsoft วางแผนที่จะเพิ่มความสามารถของ WebGL
3. ตั้งค่าฉาก
เราจะถือว่าคุณได้เลือกเบราว์เซอร์ที่รองรับเทคโนโลยีการแสดงผลทั้งหมด และคุณต้องการแสดงผลด้วย Canvas หรือ WebGL เนื่องจากเป็นตัวเลือกมาตรฐานมากกว่า Canvas ได้รับการรองรับในวงกว้างกว่า WebGL แต่ควรทราบว่า WebGL จะทำงานบน GPU ของการ์ดกราฟิก ซึ่งหมายความว่า CPU จะมุ่งเน้นไปที่งานอื่นๆ ที่ไม่เกี่ยวข้องกับการแสดงผล เช่น ฟิสิกส์หรือการโต้ตอบของผู้ใช้ที่คุณพยายามทำ
ไม่ว่าคุณจะเลือกโปรแกรมแสดงผลใดก็ตาม โปรดทราบว่า JavaScript จะต้องได้รับการเพิ่มประสิทธิภาพเพื่อการทำงาน 3 มิติไม่ใช่งานที่เบาสำหรับเบราว์เซอร์ (และเป็นเรื่องที่ยอดเยี่ยมมากที่ทำได้) ดังนั้นโปรดตรวจสอบว่าคอขวดอยู่ในโค้ดส่วนใดและนำออกหากทำได้
เมื่อทราบข้อมูลข้างต้นและสมมติว่าคุณดาวน์โหลดและรวม 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. การสร้าง Mesh
เรามีฉาก กล้อง และโปรแกรมแสดงผล (ฉันเลือกใช้ WebGL ในโค้ดตัวอย่าง) แต่ยังไม่มีสิ่งที่จะวาด อันที่จริง Three.js รองรับการโหลดไฟล์มาตรฐาน 2-3 ประเภท ซึ่งเหมาะอย่างยิ่งหากคุณกำลังส่งออกโมเดลจาก 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 โดยจะมีวัสดุทั่วไป (และมีประโยชน์มาก) หลายรายการให้คุณนำไปใช้กับเมช
- "พื้นฐาน" - ซึ่งหมายความว่าจะแสดงผลแบบ "ไม่ใช้แสง"
- Lambert
- Phong
ยังมีอีกมากมาย แต่เราจะให้คุณค้นพบด้วยตัวเองเพื่อไม่ให้เกิดความซับซ้อน ในกรณีของ WebGL เนื้อหาเหล่านี้จะมีประโยชน์อย่างยิ่ง เหตุผล เนื่องจากใน WebGL คุณต้องเขียน Shader สำหรับทุกอย่างที่แสดงผล Shader เป็นหัวข้อที่ใหญ่มาก แต่สรุปสั้นๆ ก็คือ Shader เขียนด้วย GLSL (OpenGL Shader Language) ซึ่งบอก GPU ว่าสิ่งต่างๆ ควรมีลักษณะอย่างไร ซึ่งหมายความว่าคุณต้องเลียนแบบคณิตศาสตร์ของแสง การสะท้อน และอื่นๆ การดำเนินการนี้อาจซับซ้อนขึ้นอย่างรวดเร็ว โชคดีที่มี Three.js คุณจึงไม่ต้องดำเนินการนี้หากไม่ต้องการ เนื่องจาก Three.js จะจัดการให้คุณ อย่างไรก็ตาม หากต้องการเขียน Shader คุณก็ทำได้เช่นกันด้วย MeshShaderMaterial การตั้งค่าจึงมีความยืดหยุ่น
แต่ตอนนี้เรามาติดวัสดุ Lambert บนทรงกลมกัน
// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});
นอกจากนี้ เราขอชี้แจงด้วยว่ามีพร็อพเพอร์ตี้อื่นๆ ที่คุณระบุได้เมื่อสร้างวัสดุนอกเหนือจากสี เช่น การทำให้เรียบหรือแผนที่สภาพแวดล้อม คุณควรดูหน้า Wiki เพื่อดูพร็อพเพอร์ตี้ต่างๆ ที่คุณตั้งค่าในวัสดุได้ และที่สำคัญคือวัตถุทั้งหมดที่เครื่องมือมีให้ นอกจากนี้ 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);
อย่างไรก็ตาม คุณอาจต้องการแสดงผลมากกว่า 1 ครั้ง ดังนั้นหากต้องการทำลูป คุณควรใช้ requestAnimationFrame เนื่องจากเป็นวิธีที่ฉลาดที่สุดในการจัดการภาพเคลื่อนไหวในเบราว์เซอร์ ยังไม่มีการรองรับอย่างเต็มรูปแบบ เราจึงขอแนะนำให้ดูชิมสำหรับ Paul Irish
8. พร็อพเพอร์ตี้ออบเจ็กต์ทั่วไป
หากสละเวลาดูโค้ดของ Three.js คุณจะเห็นออบเจ็กต์จำนวนมากที่ "รับค่ามา" จาก Object3D นี่คือออบเจ็กต์พื้นฐานซึ่งมีพร็อพเพอร์ตี้ที่มีประโยชน์มาก เช่น ข้อมูลตำแหน่ง การหมุน และมาตราส่วน โดยเฉพาะอย่างยิ่ง พื้นผิวทรงกลมของเราคือเมชที่รับค่ามาจาก 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;
ยังมีอีกหลายวิธี แต่เราพบว่า 2 วิธีนี้มีประโยชน์มากที่สุด คุณควรแจ้งเฉพาะรายการที่มีการเปลี่ยนแปลงเพื่อหลีกเลี่ยงการคำนวณที่ไม่จำเป็น
บทสรุป
เราหวังว่าข้อมูลเบื้องต้นเกี่ยวกับ Three.js นี้จะเป็นประโยชน์กับคุณ ไม่มีอะไรดีไปกว่าการลงมือทำและลองใช้สิ่งใหม่ๆ เราขอแนะนำอย่างยิ่ง โมเดล 3 มิติที่ทำงานในเบราว์เซอร์ได้โดยตรงนั้นสนุกมาก และการใช้เครื่องมืออย่าง Three.js จะช่วยลดความยุ่งยากให้คุณได้สร้างสรรค์สิ่งเจ๋งๆ เพื่อเป็นการช่วยเหลือคุณ เราจึงได้รวมซอร์สโค้ดไว้ในบทความนี้เพื่อให้คุณใช้เป็นข้อมูลอ้างอิง หากชอบเนื้อหานี้ โปรดแจ้งให้เราทราบทาง Twitter เรายินดีที่ได้พูดคุยกับคุณเสมอ