ตอนที่ 23: Perspective Projection: จำลองความลึกของดวงตาด้วยเวทมนตร์หารแกน W

1. 🎯 ตอนที่ 23: Perspective Projection: จำลองความลึกของดวงตา
2. 📖 เปิดฉาก (The Hook)
สวัสดีครับนักสร้างโลกจินตนาการทุกคน! ยินดีต้อนรับกลับสู่โรงงานผลิตภาพในซีรีส์ ปูพื้นฐานคณิตศาสตร์สู่โลกคอมพิวเตอร์กราฟิก ครับ
ในตอนที่แล้ว เราได้รู้จักกับออร์โทกราฟิก (Orthographic) ที่วาดทุกอย่างในขนาดเท่าเดิมไม่ว่าจะใกล้หรือไกล แต่นั่นไม่ใช่สิ่งที่มนุษย์อย่างเราเห็นในโลกความเป็นจริงใช่ไหมครับ? ในโลกความจริง ดวงตาของเรา (และเลนส์กล้องถ่ายรูป) มีคุณสมบัติพิเศษที่เรียกว่า Perspective Foreshortening หรือการที่ “ของไกลดูเล็ก ของใกล้ดูใหญ่”
ลองนึกภาพเกม FPS เวลาที่คุณมองไปตามรางรถไฟ เส้นรางที่ขนานกันจะค่อยๆ บีบเข้าหากันจนบรรจบที่จุดรวมสายตา (Vanishing Point) หรือเวลามังกรยักษ์เดินเข้ามาใกล้เรา โมเดลของมันจะขยายใหญ่ขึ้นจนล้นจอ! วันนี้พี่จะพาไปเจาะลึกสุดยอดเวทมนตร์คาถาบทสุดท้ายของ Graphics Pipeline สิ่งที่หลอกสมองมนุษย์ให้เชื่อว่าหน้าจอแบนๆ มี “มิติความลึก” ซ่อนอยู่… ยินดีต้อนรับเข้าสู่โลกของ “Perspective Projection Matrix” ครับ!
3. 🧮 จากตัวเลขสู่กราฟิก (Math to Graphics Foundation)
การจะทำให้ของที่อยู่ไกลดูเล็กลง ในทางคณิตศาสตร์นั้นเรียบง่ายมากครับ หลักการเบื้องหลังมันก็คือความรู้มัธยมต้นเรื่อง “สามเหลี่ยมคล้าย (Similar Triangles)” นั่นเอง
สมมติว่าดวงตาของเราอยู่ที่จุดกำเนิด $(0,0,0)$ และหน้าจอคอมพิวเตอร์ (Projection Plane) วางอยู่ห่างออกไปเป็นระยะทาง $d$ หากมีจุด Vertex ของมอนสเตอร์อยู่ที่พิกัด $(x, y, z)$ ในโลก 3 มิติ เมื่อเราลากเส้นตรงจากจุดนั้นวิ่งเข้าหาดวงตาของเรา เส้นตรงนี้จะไปตัดทะลุหน้าจอคอมพิวเตอร์ที่พิกัด $(x’, y’)$ ด้วยกฎของสามเหลี่ยมคล้าย เราจะได้สมการว่า: $$ \frac{y’}{d} = \frac{y}{z} \implies y’ = \frac{d \cdot y}{z} $$ $$ \frac{x’}{d} = \frac{x}{z} \implies x’ = \frac{d \cdot x}{z} $$
เห็นอะไรไหมครับ? เราต้องเอาระยะความลึก ($z$) ไปหารตัวแปรพิกัด $x$ และ $y$! ยิ่งวัตถุอยู่ไกล (ค่า $z$ มาก) ผลหารก็จะยิ่งน้อย ทำให้ภาพที่ออกมาบนจอมีขนาดเล็กลง! นี่แหละครับคือแก่นแท้ของมุมมองแบบ Perspective!
4. 📐 เจาะลึกเรขาคณิตและการประมวลผลภาพ (Geometry & Image Processing)
แต่เดี๋ยวก่อน! เรามีปัญหาใหญ่ระดับชาติครับ… “Matrix ทำได้แค่การคูณและการบวก มันไม่สามารถทำคำสั่ง ‘หาร’ ได้!” แล้วเราจะยัดสมการหารด้วย $z$ ลงไปในตาราง Matrix $4 \times 4$ ได้อย่างไร?
และนี่คือช่วงเวลาที่เวทมนตร์ของ มิติที่ 4 (Homogeneous Coordinates) หรือแกน $W$ ที่เราอัญเชิญมาในตอนที่ 14 จะได้เปล่งประกายอย่างแท้จริง!
นักคณิตศาสตร์กราฟิกได้ออกแบบโครงสร้างของ Perspective Projection Matrix ($M_{per}$) เอาไว้โดยมีเป้าหมายเดียวคือการ “แฮ็ก” มิติที่ 4 ครับ! ลองดูแถวสุดท้าย (บรรทัดล่างสุด) ของ Matrix ตัวนี้ดูสิครับ (อิงตามระบบ OpenGL): $$ M_{per} = \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0 \ 0 & 0 & \frac{-(f+n)}{f-n} & \frac{-2fn}{f-n} \ 0 & 0 & -1 & 0 \end{bmatrix} $$
ความลับระดับจักรวาลซ่อนอยู่ในบรรทัดล่างสุดที่เขียนว่า $[0, 0, -1, 0]$ ครับ! เมื่อเราเอา Matrix นี้ไปคูณกับพิกัด $[x, y, z, 1]^T$ ผลลัพธ์ของมิติที่ 4 ($w’$) จะถูกคำนวณแบบนี้: $$ w’ = (0 \cdot x) + (0 \cdot y) + (-1 \cdot z) + (0 \cdot 1) = -z $$
ทาดา! ค่าความลึก ($z$) ถูกแอบขโมยไปเก็บไว้ในตัวแปร $w’$ แล้วครับ! คาถานี้เป็นการเตรียมความพร้อม เพื่อส่งต่อให้ฮาร์ดแวร์ทำงานขั้นต่อไป
5. 🎮 เวทมนตร์นี้ในโลกความจริง (Real-World Game Applications)
เวทมนตร์ Perspective นำไปสู่ระบบสำคัญใน Game Engine มากมายครับ:
- Field of View (FOV) และการซูม: ในเกม FPS เวลาคุณกดเล็งปืนสไนเปอร์ ภาพจะซูมเข้ามา เบื้องหลังคือ Game Engine เข้าไปปรับค่า $n$ (Near Plane) และความกว้างของหน้าจอในสมการ Matrix ด้านบน ทำให้มุมมอง (FOV) แคบลง วัตถุจึงถูกขยายให้ใหญ่ขึ้นบนหน้าจอ!
- View Frustum Culling: ขอบเขตการมองเห็นของกล้องแบบ Perspective จะมีรูปทรงเป็น ปิรามิดหัวตัด (Frustum) (กว้างออกเมื่ออยู่ไกล) Game Programmer จะใช้รูปทรงเรขาคณิตนี้เช็คว่าโมเดลไหนอยู่นอกกรอบสายตาบ้าง ถ้านอกกรอบก็จะสั่งให้ GPU ข้ามการวาดสิ่งนั้นไปเลย เพื่อเซฟเฟรมเรต!
- ปัญหา Z-Fighting: การหารด้วย $z$ ทำให้ความแม่นยำของความลึก (Depth/Z-Buffer) เป็นแบบ “ไม่เป็นเชิงเส้น (Non-linear)”! GPU จะมีความละเอียดอ่อนมากเวลาวัตถุอยู่ใกล้ตา แต่ถ้าของอยู่ไกลๆ ความแม่นยำจะลดลงฮวบฮาบ นี่คือเหตุผลที่เวลาคุณมองภูเขาไกลๆ ในเกม พื้นผิวของภูเขามันจะกระพริบทับกันมั่วไปหมด (Z-Fighting) ครับ!
6. 🏭 เปิดโรงงานผลิตภาพ (The Graphics Pipeline)
เมื่อเมทริกซ์ถูกคูณเสร็จใน Vertex Shader พิกัดจะกลายเป็น $[x’, y’, z’, w’]$ แต่มันยังวาดลงจอไม่ได้นะครับ!
เมื่อหลุดออกจาก Vertex Shader ฮาร์ดแวร์ของการ์ดจอ (GPU) จะมีวงจรพิเศษที่ทำงานอัตโนมัติ (Fixed-function hardware) กระบวนการนี้เรียกว่า Perspective Divide (หรือ Homogeneous Division)
ฮาร์ดแวร์จะบังคับเอาค่า $w’$ ไป “หาร” ทุกๆ แกนอย่างบ้าคลั่ง! $$ \text{Normalized Device Coordinates (NDC)} = \left[ \frac{x’}{w’}, \frac{y’}{w’}, \frac{z’}{w’} \right] $$ ซึ่งเรารู้แล้วว่า $w’ = -z$ ดังนั้นการหารด้วย $w’$ ก็คือการหารด้วยความลึกนั่นเอง! วัตถุที่อยู่ไกล ($w’$ มีค่ามาก) เมื่อนำไปหาร พิกัด $x$ และ $y$ บนหน้าจอก็จะหดเล็กลงทันที
ด้วยการคูณ Matrix 1 ครั้งและการหารอัตโนมัติอีก 1 ครั้ง รูปทรงปิรามิดหัวตัด (Frustum) ในโลก 3D อันกว้างใหญ่ จะถูกบีบอัดจนกลายเป็น กล่องลูกบาศก์มาตรฐาน (Canonical View Volume) ที่มีขนาด $-1$ ถึง $1$ พอดีเป๊ะ พร้อมที่จะนำไปลงสี (Rasterization) บนพิกเซลหน้าจอคอมพิวเตอร์ของคุณแล้วครับ!
7. 🏁 บทสรุป (Level Cleared!)
เคลียร์ไปอีกหนึ่งสเตจระดับมหากาพย์! ตอนนี้เรารู้แล้วว่าความลึกที่คุณเห็นในหน้าจอ 2 มิตินั้น แท้จริงแล้วคือภาพลวงตาอันงดงามที่เกิดจาก “สามเหลี่ยมคล้าย” การจัดฉากนำค่า $z$ ไปยัดใส่แกน $W$ ในตาราง Matrix และปล่อยให้ GPU ดำเนินการเชือดเฉือนด้วยการทำ Perspective Divide
ถึงจุดนี้ คุณได้ครอบครองวิชา “การแปลงพิกัด (Transformation Pipeline)” ครบทุกขั้นตอนแล้วครับ! ตั้งแต่การปั้นโมเดล ย้ายไปวางบนแผนที่ (Model Matrix) ดึงโลกทั้งใบมาไว้หน้ากล้อง (View Matrix) และบีบอัดความลึกให้แบนราบลงบนจอ (Perspective Projection) สิ่งนี้คือแกนกลางของ Graphics Engine ทุกตัวบนโลก!
แต่เดี๋ยวก่อน! ในระหว่างทางเราติดค้างหนี้สินกันไว้เรื่องหนึ่ง… จำความน่าปวดหัวของการหมุนโมเดล 3 มิติ (Euler Angles) ที่นำไปสู่อาการบั๊ก “Gimbal Lock” ได้ไหมครับ? ในตอนต่อไป เราจะมาปลดล็อกสุดยอดอาวุธคณิตศาสตร์ที่แก้ปัญหานี้ได้อย่างหมดจด… เตรียมตัวพบกับเวทมนตร์มิติที่ 4 ที่แท้จริง “Quaternions (ควอเทอร์เนียน)” ได้เลยครับ Level Cleared!
สนใจพูดคุยแลกเปลี่ยนเทคนิคการพัฒนาเกม คอมพิวเตอร์กราฟิก หรือออกแบบระบบซอฟต์แวร์? ทีมงาน WP Solution พร้อมให้บริการออกแบบและพัฒนาซอฟต์แวร์แบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p