ตอนที่ 24: View Frustum Culling: เวทมนตร์สแกนกรรม ตัดขอบฟ้าทิ้งเพื่อเซฟพลังการ์ดจอ!

1. 🎯 ตอนที่ 24: View Frustum: ตัดขอบฟ้าทิ้งด้วยคณิตศาสตร์
2. 📖 เปิดฉาก (The Hook)
สวัสดีครับนักสร้างโลกจินตนาการทุกคน! ยินดีต้อนรับกลับสู่โรงงานผลิตภาพในซีรีส์ ปูพื้นฐานคณิตศาสตร์สู่โลกคอมพิวเตอร์กราฟิก ครับ
คุณเคยสงสัยไหมครับว่า เกมแนว Open World ฟอร์มยักษ์อย่าง GTA หรือ The Witcher ที่มีเมืองทั้งเมือง มีภูเขา ต้นไม้ และผู้คนเดินไปมานับหมื่นชีวิต… ทำไมคอมพิวเตอร์ของเราถึงยังเรนเดอร์ภาพเหล่านั้นออกมาได้ลื่นไหลที่ 60 FPS โดยที่การ์ดจอไม่ระเบิดไปเสียก่อน?
เคล็ดลับระดับปรมาจารย์ของวงการ Game Engine ถูกสรุปไว้ด้วยประโยคทองคำประโยคเดียวครับ: “วิธีที่เร็วที่สุดในการเรนเดอร์วัตถุ ก็คือการไม่เรนเดอร์มันเลย!”
ในเมื่อดวงตาของตัวละครเรา (Camera) มองตรงไปข้างหน้า แล้วเราจะเอาเวลาอันมีค่าของ CPU และ GPU ไปคำนวณแสงเงาให้กับภูเขาที่อยู่ “ข้างหลัง” หรือต้นไม้ที่อยู่ “นอกจอ” ไปทำไมล่ะครับ? วันนี้พี่จะพาไปเจาะลึกเวทมนตร์แห่งการคัดทิ้ง ที่มีชื่อว่า “Frustum Culling” ซึ่งใช้คณิตศาสตร์ง่ายๆ มาเป็นมีดกรรไกรตัดสิ่งที่อยู่นอกสายตาทิ้งไปอย่างหมดจดครับ!
3. 🧮 จากตัวเลขสู่กราฟิก (Math to Graphics Foundation)
ก่อนที่เราจะไปคัดแยกวัตถุ เราต้องรู้จักขอบเขตสายตาของกล้องจำลองเสียก่อน ขอบเขตนี้เรียกว่า View Frustum ซึ่งมีรูปทรงเรขาคณิตคล้ายกับ “ปิรามิดที่ถูกตัดยอดทิ้ง (Pyramid with the tip snipped off)”
รูปทรงนี้ถูกสร้างขึ้นมาจาก ระนาบ 6 แผ่น (6 Clip Planes) ที่โอบล้อมพื้นที่สมมติเอาไว้ ได้แก่:
- ด้านซ้าย (Left)
- ด้านขวา (Right)
- ด้านบน (Top)
- ด้านล่าง (Bottom)
- ด้านหน้า (Near) - จุดเริ่มต้นของการมองเห็น
- ด้านหลัง (Far) - ระยะไกลสุดที่กล้องมองเห็น
จุดใดๆ ก็ตามที่อยู่ในโลก 3 มิติ จะ “ถูกมองเห็น” ก็ต่อเมื่อมันอยู่ “ข้างใน” ระนาบทั้ง 6 แผ่นนี้พร้อมๆ กัน! หากยังจำกันได้ในตอนที่ 9 สมการของระนาบ (Plane Equation) สามารถเขียนอยู่ในรูปของจุด $\mathbf{p}$ ใดๆ ที่อยู่บนระนาบ และเวกเตอร์ตั้งฉาก (Normal Vector) $\mathbf{n}$ ได้ดังนี้: $$ f(\mathbf{p}) = \mathbf{n} \cdot (\mathbf{p} - \mathbf{a}) = 0 $$ โดยที่ $\mathbf{a}$ คือจุดอ้างอิงบนระนาบ
เราสามารถใช้สมการนี้ตรวจสอบได้ว่า วัตถุอยู่ฝั่งไหนของระนาบ ถ้าผลลัพธ์ของ Dot Product มากกว่าศูนย์ แปลว่าอยู่ฝั่งเดียวกับทิศที่ Normal ชี้ไป และถ้าติดลบก็แปลว่าอยู่คนละฝั่งครับ!
4. 📐 เจาะลึกเรขาคณิตและการประมวลผลภาพ (Geometry & Image Processing)
ในความเป็นจริง โมเดล 3D มักจะประกอบด้วยโพลิกอน (Polygon) นับหมื่นชิ้น การจะเอาทุกๆ Vertex ไปนั่งเทสต์กับระนาบ 6 แผ่นนั้นเป็นเรื่องที่กินพลังงานคอมพิวเตอร์อย่างมหาศาล!
โปรแกรมเมอร์จึงใช้เทคนิคห่อหุ้มโมเดลด้วย รูปทรงห่อหุ้ม (Bounding Volumes) แบบหยาบๆ เช่น ทรงกลมห่อหุ้ม (Bounding Sphere) หรือกล่องสี่เหลี่ยม (AABB - Axis-Aligned Bounding Box) ซึ่งคำนวณง่ายกว่ากันหลายร้อยเท่า!
สมมติว่าเราห่อหุ้มต้นไม้ 1,000 โพลิกอนไว้ในทรงกลม 1 ลูก ที่มีจุดศูนย์กลาง $\mathbf{c}$ และรัศมี $r$ เราต้องการเช็คว่าทรงกลมนี้ “หลุด” ออกไปนอกหน้าจอหรือยัง เราสามารถเอาสมการระนาบมาใช้ได้เลยครับ! เราจะหาระยะห่างแบบมีเครื่องหมาย (Signed Distance) จากจุดศูนย์กลางทรงกลม $\mathbf{c}$ ไปยังระนาบ (สมมติว่า Normal ชี้ออกไปนอกหน้าจอ): $$ \frac{(\mathbf{c} - \mathbf{a}) \cdot \mathbf{n}}{|\mathbf{n}|} > r $$ หากระยะห่างจากศูนย์กลางไปยังระนาบ มีค่าเป็นบวกและ “มากกว่ารัศมี ($r$)” ของทรงกลมเสียอีก แปลว่าทรงกลมทั้งลูกนั้นหลุดลอยออกไปอยู่นอกมุมกล้องแบบ 100% (Outside the clipping plane), เราก็สามารถเตะต้นไม้ต้นนี้ทิ้งออกจากหน่วยความจำของเฟรมนั้นๆ ได้เลย!
5. 🎮 เวทมนตร์นี้ในโลกความจริง (Real-World Game Applications)
กระบวนการค้นหาและทิ้งวัตถุที่ไม่จำเป็นนี้ เรียกว่า Culling (การคัดออก) ครับ,
- View Frustum Culling: นี่คือด่านตรวจคนเข้าเมืองด่านแรกของทุก Game Engine (เช่น Unity, Unreal) หากเรามีฉากป่าไม้ที่มีต้นไม้ 10,000 ต้น ทันทีที่เราเช็ค Bounding Sphere แล้วพบว่าต้นไม้ 8,000 ต้นอยู่หลังกล้องหรืออยู่นอกจอ เราจะส่งต้นไม้แค่ 2,000 ต้นไปให้ GPU ทำงานต่อ มันคือการช่วยชีวิตการ์ดจออย่างแท้จริง!
- Occlusion Culling: บางครั้งวัตถุอยู่ “ในกรอบสายตา (View Frustum)” ก็จริง แต่ดันถูกตึกขนาดใหญ่บังจนมิด เกมสมัยใหม่ก็จะมีระบบคำนวณซ้อนไปอีกชั้น เพื่อคัดวัตถุที่ถูกบัง (Occluded) ทิ้งไปเช่นกัน
- Level of Detail (LOD): หากวัตถุอยู่ไกลกล้องมากๆ แม้จะไม่หลุดจอ แต่พื้นที่ที่มันแสดงบนจอ (Pixel coverage) อาจจะเล็กนิดเดียว เกมจะลดทอนรายละเอียดของโมเดลลง (เช่น เปลี่ยนจาก 10,000 โพลิกอน เหลือแค่ 100 โพลิกอน) เพื่อลดภาระการประมวลผล
6. 🏭 เปิดโรงงานผลิตภาพ (The Graphics Pipeline)
เพื่อให้เข้าใจชัดเจน เราต้องแยกให้ออกระหว่าง Culling กับ Clipping ใน Graphics Pipeline ครับ:
- Culling (ทำใน CPU): เกิดขึ้น “ก่อน” ที่จะส่งข้อมูลเข้าการ์ดจอ เป็นการคัดทิ้งในระดับ “วัตถุทั้งชิ้น” (Object-level) เพื่อลดจำนวน Draw Calls
- Clipping (ทำใน GPU): เมื่อวัตถุส่วนใหญ่ผ่าน Culling เข้ามาได้แล้ว จะมีบางวัตถุที่ “คร่อม” อยู่บนเส้นขอบจอพอดี (เช่น รถยนต์ที่โผล่มาแค่ครึ่งคัน) GPU จะทำการใช้สมการคณิตศาสตร์เอา “กรรไกร” มาตัด (Clip) โพลิกอนที่ล้นขอบจอให้ขาดออก เพื่อป้องกันไม่ให้คอมพิวเตอร์พยายามวาดภาพลงบนพิกเซลที่ไม่มีอยู่จริง ซึ่งมักใช้อัลกอริทึมอย่าง Sutherland-Hodgman ในการจัดการ
การทำงานร่วมกันของ Culling และ Clipping คือปราการเหล็กที่ทำให้กระบวนการ Rasterization ปลอดภัยและทำงานได้อย่างรวดเร็วที่สุด!
7. 🏁 บทสรุป (Level Cleared!)
เคลียร์ไปอีกด่านแล้วครับ! ทฤษฎีเรขาคณิตพื้นฐานอย่างสมการระนาบ (Plane) นำมาสู่อัลกอริทึมขั้นเทพอย่าง View Frustum Culling ที่ช่วยลดภาระคอมพิวเตอร์ลงไปได้อย่างมหาศาล ทำให้เกมสามารถเนรมิตโลกอันกว้างใหญ่ได้โดยยังคง Frame Rate ที่ลื่นไหล
ในขณะนี้ เราได้เรียนรู้เวทมนตร์การคุมมุมมองและพื้นที่หน้าจอไปจนหมดแล้ว แต่พี่เคยเกริ่นไว้หลายตอนแล้วใช่ไหมครับว่าการใช้ Matrix หมุนตัวละคร (Euler Angles) นั้นมีจุดอ่อนที่น่ากลัวซ่อนอยู่… ถึงเวลาแล้วครับที่เราจะก้าวเข้าสู่ศาสตร์มืดแห่งการหมุนในมิติที่ 4! ตอนต่อไปเตรียมพบกับ “Quaternions (ควอเทอร์เนียน)” ที่จะมาปฏิวัติวิธีการหมุนในโลก 3 มิติไปตลอดกาล เตรียมไม้กายสิทธิ์ให้พร้อม Level Cleared!
สนใจพูดคุยแลกเปลี่ยนเทคนิคการพัฒนาเกม คอมพิวเตอร์กราฟิก หรือออกแบบระบบซอฟต์แวร์? ทีมงาน WP Solution พร้อมให้บริการออกแบบและพัฒนาซอฟต์แวร์แบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p