แม่ครับ ไม่ต้องมีเมทริกซ์ก็ได้
(enkimute.github.io)- เป็นการทดลองนำ Euclidean PGA มาใช้จนสุดทางในฟอร์เวิร์ดเรนเดอร์เรอร์ที่เข้ากันได้กับ glTF แทนเมทริกซ์ 4x4 ที่เคยใช้กันแทบเป็นสัญชาตญาณในกราฟิก 3D
- การหมุนและการเลื่อนตำแหน่งถูกแทนด้วย PGA motor ขนาด 8 float และการประกอบ motor ทั่วไปใช้ 48 การคูณ·40 การบวก ซึ่งน้อยกว่าเมทริกซ์ 4x4 ที่ใช้ 64 การคูณ·48 การบวก
- การแปลงจุดหากกระจายสมการตรง ๆ จะแพงกว่าเมทริกซ์ แต่เมื่อใช้ sandwich product ที่อาศัยเงื่อนไขการทำให้เป็นปกติ จะลดลงเหลือ 21 การคูณ·18 การบวก และการแปลงทิศทาง·ทิศทางฐานยิ่งถูกกว่า
- ใน tangent space normal mapping แทนที่ normal และ tangent ด้วย tangentRotor ทำให้ข้อมูลจุดยอดลดจาก 12 float เหลือ 9 float ขณะเดียวกันปรับต้นทุนการแปลงเป็น world-space ให้อยู่ราว 47 การคูณ·38 การบวก ใกล้เคียงวิธีแบบเมทริกซ์
- เพื่อให้ทำงานกับคอนเทนต์ glTF จริงได้ ต้องแปลงเมทริกซ์เป็น motor ตอนโหลด และติดตาม uniform scale แยกเป็น float ต่างหาก ส่วน non-uniform scale ต้องจัดการแบบจำกัดหรือมีเส้นทาง fallback ไปใช้เมทริกซ์ 4x4
ฟอร์เวิร์ดเรนเดอร์เรอร์ไร้เมทริกซ์ที่สร้างด้วย PGA
- โปรเจกต์คือ Look, Ma, No Matrices มีเป้าหมายเพื่อทำ ฟอร์เวิร์ดเรนเดอร์เรอร์ที่ไม่มีเมทริกซ์
- หลัง SIGGRAPH 2019 เป็นต้นมา Geometric Algebra โดยเฉพาะ Euclidean PGA ได้รับความสนใจในชุมชนกราฟิกและแมชชีนเลิร์นนิง แต่ในกราฟิก 3D แบบดั้งเดิม หลายกรณียังหยุดอยู่แค่การเรียก dual quaternion ใหม่ว่า PGA motor
- การทำงานนี้ผสาน PGA algebra เข้ากับเอนจิน 3D ที่เข้ากันได้กับ glTF โดยไม่ใช่แค่เปลี่ยนชื่อเชิงพีชคณิต แต่จัดโครงสร้างหลายส่วนของกราฟิกไปป์ไลน์ใหม่ในแนวทาง PGA
- โค้ดอ้างอิงคือ Khronos glTF viewer และเป็นการทดลองแทนที่เมทริกซ์แบบไม่ประนีประนอม มากกว่าจะเป็นการทำเพื่อประสิทธิภาพสูงสุด
- ท้ายที่สุด hybrid solution อาจเป็นตัวเลือกที่ดีกว่า
เหตุผลที่ตั้งคำถามกับเมทริกซ์ 4x4
- เมทริกซ์ 4x4 มีบทบาทหลักมายาวนานใน graphics API และ fixed-function pipeline ของ GPU และยังคงเป็นเครื่องมือพื้นฐานของฟอร์เวิร์ดเรนเดอร์ทั่วไป
- GPU สมัยใหม่ใกล้เคียงกับ โปรเซสเซอร์สเกลาร์ที่โปรแกรมได้ มากกว่า fixed-function pipeline จึงไม่จำเป็นต้องยึดการแทนค่าแบบเมทริกซ์เป็นศูนย์กลางเสมอไป
- ในเอนจิน 3D จริง เมทริกซ์จำนวนมากเป็น orthogonal matrix ที่มีเฉพาะการหมุนและการเลื่อนตำแหน่ง
- PGA motor manifold สามารถแทน Euclidean motion ทั้งหมดได้ด้วยต้นทุนการคำนวณและหน่วยความจำที่ต่ำกว่า และยังรวม quaternion กับ dual quaternion ได้โดยไม่ต้องแปลง
การแทนข้อมูลและการดำเนินการพื้นฐานของ PGA
- PGA algebra สร้างจากเวกเตอร์ฐานสี่ตัว
e0~e3e1,e2,e3สอดคล้องกับระนาบx=0,y=0,z=0ตามลำดับ- degenerate vector พิเศษ
e0แทนระนาบที่อนันต์
- ในเชดเดอร์ใช้ชนิดข้อมูล built-in ของ GLSL เพื่อใช้การบวก การลบ และการคูณด้วยสเกลาร์ โดยไม่ต้องมี operator overloading
motor mat2x4line mat2x3point vec3direction vec3
- การประกอบ PGA motor ทั่วไปทำด้วย geometric product
- การคูณเมทริกซ์ 4x4: 64 การคูณ, 48 การบวก
- การประกอบ motor ทั่วไป
gp_mm: 48 การคูณ, 40 การบวก
- ในชุดการแปลงแบบพิเศษ สามารถใช้การดำเนินการที่ถูกกว่าได้
gp_rr: 16 การคูณ, 12 การบวกgp_tt: 0 การคูณ, 3 การบวกgp_rt/gp_tr: 12 การคูณ, 8 การบวกgp_rm/gp_mr: 32 การคูณ, 24 การบวกgp_tm/gp_mt: 12 การคูณ, 12 การบวก
การปรับแต่งการแปลงจุด·ทิศทาง
- ใน PGA เมื่อแปลงจุด
pด้วย motorMจะใช้ sandwich productM p M̃ - หากกระจายสมการตรง ๆ จะใช้ 33 การคูณ, 29 การบวก ซึ่งมากกว่าการคูณเมทริกซ์-เวกเตอร์ที่ใช้ 16 การคูณ, 12 การบวก
- หากใช้ข้อเท็จจริงว่า motor ที่ normalize แล้วเป็นไปตาม
M M̃ = 1เพื่อจัดรูปสมการใหม่ จะลดการแปลงจุดลงเหลือ 21 การคูณ, 18 การบวก - ทิศทาง หรือจุดที่อนันต์ มีสัมประสิทธิ์
e123โดยนัยเป็น 0 จึงถูกกว่า- การแปลงทิศทางทั่วไป: 18 การคูณ, 12 การบวก
- การแปลง basis direction เช่น การแปลงแกน x สามารถลดได้ถึง 6 การคูณ, 4 การบวก
- การปรับแต่ง basis direction นี้กลายเป็นหลักฐานที่สั่นคลอนความเชื่อเดิมว่าเมทริกซ์เร็วที่สุดเสมอในการจัดการ tangent frame ภายหลัง
การทำให้เป็นปกติ, รากที่สอง, แมปเอ็กซ์โปเนนเชียล·ลอการิทึม
- squared pseudonorm ของ PGA motor อยู่ในรูป
M M̃ = a + b e0123ซึ่งเป็น Study Number - การ normalize ไม่ใช่แค่การ normalize เวกเตอร์ธรรมดา แต่เป็นขั้นตอนที่รับประกันว่า motor ผลลัพธ์จะเป็น orthonormal transformation
- ต้นทุนการทำ normalize สำหรับ motor ทั่วไป: 21 การคูณ, 5 การบวก
- สำหรับ pure translation หรือ rotation สามารถใช้เวอร์ชันที่มีประสิทธิภาพกว่าได้
- rigid transformation ระหว่างจุดสองจุด·เส้นสองเส้น·ระนาบสองระนาบ
a,bแทนได้ด้วยM = sqrt(b / a)- geometric product
baขององค์ประกอบสองตัวชนิดเดียวกันจะสร้าง motor ที่สอดคล้องกับการแปลงจากaไปbเป็นสองเท่า - สามารถคำนวณได้ในรูป
sqrt M = normalize(1 + M)
- geometric product
- logarithm ของ PGA motor คือ scaled line และ scaled line สามารถสร้าง rotation motor ได้ด้วย exponentiation
- exponential map ของเมทริกซ์ 4x4 ทั่วไปมีต้นทุนเชิงตัวเลขสูง แต่บน PGA motor manifold สามารถมี closed form ที่มีประสิทธิภาพ ได้
อินเวิร์สและ motor factorization
- Geometric Algebra สามารถคำนวณอินเวิร์สของวัตถุที่ normalize แล้วได้อย่างมีประสิทธิภาพ
- plane inverse: ตัวมันเอง
- line inverse: กลับเครื่องหมาย
- point inverse: กลับเครื่องหมาย
- motor inverse: reversion
- เมื่อ bivector ทั่วไปไม่เป็นไปตาม Plücker condition จึงไม่แทนเส้นเดี่ยว จะคำนวณอินเวิร์สด้วย Study Number inverse
- ในการทำเรนเดอร์มีการใช้ factorization สองแบบ
- Euclidean factorization: แยก motor เป็น rotation รอบ origin แล้วตามด้วย translation
- Invariant factorization: แยก motor เป็น translation และ rotation ที่ commute กัน ซึ่งใน 3D รู้จักกันในรูปของ Mozzi-Chasles theorem
- เมื่อต้องประกอบ tangent frame กับ object-to-world motor การใช้ Euclidean factorization มีประโยชน์เพราะคุณสมบัติของ frame ที่ invariant ต่อ translation
การจัดการเมทริกซ์ glTF และ scale
- เพื่อให้ทำงานร่วมกับคอนเทนต์ glTF เดิมได้ ต้องแปลงเมทริกซ์เป็น PGA motor ตอนโหลด
- 4x4 orthogonal matrix แปลงเป็น motor โดยใช้ isomorphism กับ quaternion
- matrix และ transformation ทั้งหมดที่ import เข้ามาจะถูกแปลงตอน load time
- PGA motor จัดการ rigid body transformation จึงไม่รวม scaling
- uniform scaling invariant ต่อ rotation และ translation จึงติดตามได้ด้วย float หนึ่งตัวต่อแต่ละโหนด
- total scale ของแต่ละองค์ประกอบคำนวณจากผลคูณของ scale ตัวเองกับ parent scale
- ใช้ total scale กับ vertex ตอน load time หรือในขั้นแรกของ vertex shader
- ใช้ parent scale กับ translation ตอน load time และตอน animation update
- จากตัวอย่างไฟล์ glTF แบบสุ่มประมาณ 400 ไฟล์ พบกรณีที่มี scale animation น้อยกว่า 0.5% และ fixed uniform scale พบได้ค่อนข้างมาก
- non-uniform scaling ไม่ invariant ต่อ rotation จึงยุ่งยากกว่า
- การจัดการ non-uniform scale ทั่วไปเลี่ยงเส้นทาง fallback ด้วยเมทริกซ์ 4x4 ได้ยาก
- ในตัวอย่าง glTF พบกรณีที่ non-uniform scale ถูกใช้เฉพาะกับ leaf node และในกรณีนี้จะใช้ scale แยกต่างหากก่อนการแปลงที่เหลือ โดยไม่กระทบ animation key
การแทนที่ Model-View-Projection
- ฟอร์เวิร์ดเรนเดอร์เรอร์แปลง mesh geometry ใน object space ไปเป็น screen space และกำหนดว่าแต่ละ triangle ครอบคลุม pixel ใด
- ในบรรดา model, view, projection matrix ของไปป์ไลน์ทั่วไป จะแทนที่ model และ view ด้วย PGA motor
- ตำแหน่ง vertex ใช้
sw_mp - ทิศทาง normal และ tangent ใช้
sw_md
- ตำแหน่ง vertex ใช้
- โดยทั่วไป projection matrix มี non-zero entry เพียง 5 ตัว จึงไม่ฝืนแปลงเป็น PGA แต่ใช้ expression สำหรับ projection โดยตรง
- การอัปเดต scene graph hierarchy ฝั่ง CPU ใช้ motor composition แทน matrix composition ทำให้ปริมาณการคำนวณลดลง
- การแปลง vertex ฝั่ง GPU หากเทียบแบบตรง ๆ motor อาจดูเสียเปรียบ แต่เมื่อเปลี่ยนการแทนค่า tangent frame ผลลัพธ์จะต่างออกไป
การปรับแต่ง tangent space normal mapping
- vertex shader ของ mesh ที่ทำ tangent space normal mapping โดยทั่วไปต้องแปลง position, normal, tangent
- normal, tangent, bitangent ประกอบกันเป็น orthonormal frame ดังนั้นใน PGA สามารถแทนด้วย tangentRotor ที่พา canonical basis frame ไปยัง tangent frame ที่ต้องการ
- วิธีนี้ลดขนาด vertex descriptor
- แบบเดิม: position 3 + normal 3 + tangent 4 + uv 2 = 12 floats
- แบบ PGA: position 3 + tangentRotor 4 + uv 2 = 9 floats
- จำนวน float ต่อจุดยอดลดลง 25%
- tangentRotor มี double cover และใช้ sign ของ scalar coefficient ให้ตรงกับ classical handedness flag เพื่อแยก even/odd k-reflection
- อาศัย signed zero และใน vertex shader ดึง handedness ด้วย
sign(1/tangentRotor.x)
- อาศัย signed zero และใน vertex shader ดึง handedness ด้วย
- หากแปลง position, normal, tangent ด้วยเมทริกซ์ 4x4 จะต้องใช้ทั้งหมด 48 การคูณ, 36 การบวก
- วิธี PGA แปลง tangent frame ทั้งชุดในครั้งเดียว แล้วดึง normal และ tangent ออกมา
- การประกอบ tangent frame: 16 การคูณ, 12 การบวก
- การดึง normal/tangent: 9 การคูณ, 8 การบวก
- การแปลง position: 21 การคูณ, 18 การบวก
- การคูณ 1 ครั้งสำหรับดึง handedness
- รวม 47 การคูณ, 38 การบวก
- ต้นทุนการแปลงจุดยอดแทบเท่ากับวิธีเมทริกซ์ และการเก็บ transform ลดจาก 32 floats เหลือ 8 floats
fragment shader และข้อจำกัดของ baked texture
- เพื่อโหลดคอนเทนต์เดิม ขั้น fragment shader ยังต้องใช้ TBN matrix อีกครั้ง
- baking tool จะ interpolate vertex normal และ tangent บน triangle face ในกระบวนการ bake high-detail mesh ลงบน low-detail mesh แล้วสร้าง orthogonal TBN matrix ที่แต่ละ fragment เพื่อทำ tangent space normal texture
- การ interpolate basis vector ทำให้เกิดความคลาดเคลื่อนแบบฉบับของวิธีเมทริกซ์ และความคลาดเคลื่อนนั้นถูก baked อยู่ใน texture แล้ว
- ดังนั้น implementation นี้จึงดึง normal และ tangent vector ออกจาก tangentRotor อย่างชัดเจน
- หากควบคุม baking tool ได้ ก็สามารถส่ง tangentRotor ไปยัง fragment shader ได้ตรง ๆ แล้ว normalize จากนั้นใช้แปลง sampled normal
- ไม่จำเป็นต้องสร้าง TBN matrix
- ไม่จำเป็นต้องดึง normal/tangent ใน vertex shader
- ลด varying parameter ได้หนึ่งตัว
- ตัด expensive orthogonalization ใน fragment shader ออกได้ด้วย
motor skinning และ animation blending
- PGA motor isomorphic กับ dual quaternion จึงนำไปใช้กับ skinning ได้อย่างเป็นธรรมชาติ
- หลังแปลง inverse bind matrix เป็น motor แล้ว จะ blend bone motor ด้วยรูปแบบเดียวกับ dual quaternion skinning
- transformation ที่ถูก blend จะปรับเครื่องหมายให้เดินตาม shortest arc และ normalize transformation ผลลัพธ์อีกครั้ง
- animation blending ก็ทำแบบเดียวกัน โดย blend PGA motor โดยตรงบน CPU แล้ว normalize
ผลลัพธ์ของการทดลองแทนที่เมทริกซ์
- การทำ implementation ที่แทนที่เมทริกซ์ด้วย PGA ล้วน ๆ ในฟอร์เวิร์ดเรนเดอร์เรอร์ที่เข้ากันได้กับ glTF นั้นเป็นไปได้
- ความคาดหมายว่าต้นทุนการแปลงจะแพงกว่า ไม่ได้เรียบง่ายเช่นนั้นเมื่อใช้การแทน tangent frame และการปรับแต่ง sandwich product
- ในกรณีทั่วไปของ tangent space normal mapping วิธี PGA motor ทำให้ต้นทุน vertex shader แทบเท่าวิธีเมทริกซ์ พร้อมกับลด memory footprint ของ vertex ได้มาก
- การปรับปรุงด้านหน่วยความจำที่เก็บ vertices ได้มากขึ้นราว 33% ในพื้นที่เท่าเดิมนั้นเด่นเป็นพิเศษ
- เทคนิคนี้สามารถนำไปใช้กับเอนจิน 3D เดิมได้ในฐานะ drop-in replacement โดยแทบไม่เพิ่มต้นทุน vertex shader และไม่ต้องแก้ส่วนอื่นของไปป์ไลน์
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
Freya Holmér หนึ่งในผู้สร้าง YouTube ด้านคณิตศาสตร์/กราฟิกที่ผมชอบ เพิ่งทำวิดีโอแนะนำพีชคณิตเชิงเรขาคณิตออกมาได้ดีมาก: https://www.youtube.com/watch?v=htYh-Tq7ZBI&ab_channel=Freya...
ถ้าสนใจกราฟิก 3D โดยเฉพาะสไปลน์/เส้นโค้งเบซิเยร์ วิดีโอของเธอทั้งหมดก็ควรค่าแก่การดู
โดยส่วนตัวแล้วพีชคณิตเชิงเส้นเป็นเรื่องยากสำหรับผมมาตลอด แต่แนวทางแบบ พีชคณิต Clifford นี้รู้สึกเข้าใจได้โดยสัญชาตญาณมากกว่าเยอะ
ไลบรารีนี้สร้างโดย enkimute ผู้เขียนต้นฉบับ เป็นไลบรารีที่น่าทึ่งทีเดียว เพราะเป็นสคริปต์ไฟล์เดียว ไม่ต้อง build แต่ยังรองรับพีชคณิต N มิติและการเรนเดอร์ด้วย
เช่น คำอธิบายเรื่องส่วนที่ Freya ผ่านไปค่อนข้างเร็วหรือละไว้ อย่าง ความไม่สลับที่ของการคูณ ก็ทำได้ค่อนข้างดี
พีชคณิตเชิงเรขาคณิตเคยเป็นปริศนาโดยสมบูรณ์อยู่พักหนึ่ง แต่สุดท้ายพอเข้าใจแบบนี้ก็คลี่คลาย: มันก็แค่ การคูณพหุนาม เพียงแต่มีปริมาณบางอย่างที่ลำดับการคูณสำคัญ และตารางการคูณแปลก ๆ เท่านั้นเอง เช่น
i*i = 1,i*j = -j*iสื่อแนะนำส่วนใหญ่ทำให้ผลคูณเชิงเรขาคณิตของเวกเตอร์สองตัว
(x1*i + y1*j) * (x2*i + y2*j)ดูลึกซึ้งและลึกลับ แต่จริง ๆ แล้วเหมือนการกระจายแบบ FOIL ที่เรียนในพีชคณิตระดับปีหนึ่ง:(x1*i + y1*i)(x2*i+y2*j) = x1*x2*i*i + x1*y2*i*j + y1*x2*j*i + y1*y2*j*j = (x1*x2 + y1*y2) + (x1*y2 - y2*x1)*i*jค่าในวงเล็บแรกคือ dot product ที่คุ้นเคย และค่าในวงเล็บที่สองสอดคล้องกับ cross product ที่คุ้นเคย แต่ถูกแสดงด้วยฐานของมิติใหม่ชื่อ
i*jและต่างจาก cross product ตรงที่มัน generalize ไปยังมิติใด ๆ ก็ได้ ในพีชคณิตเชิงเรขาคณิตเรียกสิ่งนี้ว่า wedge productพอเข้าใจตรงนี้ การอนุมานสูตรการหมุนก็ง่ายขึ้น เพราะสามารถนำเทคนิคที่คุ้นเคยจากพีชคณิตไปใช้แก้ปัญหาเรขาคณิตได้ตรง ๆ
ถ้ากำหนดให้ค่าของเวกเตอร์คูณกับตัวเองเป็นกำลังสองของความยาวเวกเตอร์นั้น ที่เหลือทั้งหมดก็เป็นผลตามมาจากการคูณพหุนามธรรมดา สวยงามทีเดียว
“มันทำงานอย่างไร?” กับ “ทำไมมันถึงทำงาน?” เป็นสองคำถามที่ครูคณิตศาสตร์ต้องหาสมดุล และในคอร์สหนึ่ง ๆ ก็ยากที่จะตอบทั้งสองอย่างได้ดีเสมอ
cross product ของเวกเตอร์สามมิติสองตัวคือเวกเตอร์อีกตัวที่ตั้งฉากกับระนาบที่เวกเตอร์ทั้งสองสร้างขึ้น ส่วนผลคูณพีชคณิตภายนอกคือ 2-vector หรือไบเวกเตอร์ที่กวาดพื้นที่รูปสี่เหลี่ยมด้านขนานระหว่างเวกเตอร์ทั้งสอง และอยู่บนระนาบที่เวกเตอร์ทั้งสองวางอยู่ ใน 3 มิติ เวกเตอร์จาก cross product จะตั้งฉากกับระนาบไบเวกเตอร์นี้
โดยเฉพาะถ้าจะนิยามผลคูณแบบ bilinear
m:V x V -> Vบนปริภูมิเวกเตอร์Vก็เท่ากับการกำหนดmเฉพาะกับคู่ของเวกเตอร์ฐานพอดี ถ้าเรียกสิ่งนี้ว่า “สมบัติสากลของ tensor product” ก็คงได้แต่พูดว่า “อ้อ อย่างนี้นี่เอง”สำหรับ interpolation ของการหมุน มีหลายแนวทางที่น่าสนใจ ทั้ง พีชคณิตเชิงเรขาคณิต, quaternion และแม้กระทั่ง interpolation ของเมทริกซ์ทั้งตัว: https://www.gamedev.net/tutorials/programming/math-and-physi...
แต่พอ optimize โค้ดด้วยมือแล้ว โค้ดสุดท้ายของแนวทางส่วนใหญ่แทบจะคล้ายกัน ความต่างอยู่ที่ว่าเราเข้าใจกฎและความเป็นไปได้อย่างไร
เท่าที่รู้เล็กน้อย พีชคณิตเชิงเรขาคณิตดูเป็นแนวทางที่สอดคล้องและทรงพลังที่สุด มันไม่คุ้นเคย และรับเข้าไปในตอนแรกค่อนข้างหนัก แต่คนที่ข้ามกำแพงนั้นไปได้ก็มักชอบมัน
ตรงกันข้าม ทุกคนใช้ quaternion แต่ก็บ่นว่าไม่เข้าใจ และบอกว่าถ้าจะทำให้เห็นภาพต้องใช้หนังสือทั้งเล่ม อย่างหนังสือ 『Visualizing Quaternions』 ของ Andrew J. Hanson และ Steve Cunningham
พีชคณิตเชิงเรขาคณิตสนุก ส่วน quaternion ไม่สนุก พีชคณิตเชิงเรขาคณิตรู้สึกเหมือนเข้าใจแล้ว แต่ quaternion แม้จะตามเลกเชอร์และทำโจทย์ไป ก็แน่ใจได้แค่ว่ายังไม่เข้าใจ ตอนนี้พอรู้พีชคณิตเชิงเรขาคณิตบ้างแล้ว ในที่สุดก็เริ่มรู้สึกว่าเข้าใจ quaternion อยู่บ้าง
https://www.goodreads.com/en/book/show/4419538
ถ้าสนใจหัวข้อนี้ มีสไลด์ดี ๆ ที่ไล่ภาพรวมแนวคิด Grassman/Clifford/พีชคณิตเชิงเรขาคณิตอยู่ที่นี่: http://www.terathon.com/gdc12_lengyel.pdf
และยังมีเว็บดี ๆ อีกแห่ง: https://mattferraro.dev/posts/geometric-algebra
ไม่ควรพลาด “A swift introduction to projective geometric algebra” ที่ยอดเยี่ยมของ Sudgy ด้วย: https://www.youtube.com/watch?v=0i3ocLhbxJ4
และเว็บอ้างอิงหลักคือ https://bivector.net
ยังเข้าร่วม Discord ของ bivector ที่มีอาจารย์ นักวิจัย และผู้สนใจมากกว่า 1,000 คนได้ด้วย: https://discord.gg/vGY6pPk
พูดตามตรง ผมไม่ค่อยชอบวิธีที่พีชคณิตเชิงเรขาคณิตทำให้เกิด องค์ประกอบผสม สารพัดแบบ ถ้าไม่ระวังว่ากำลังเอาอะไรไปคูณกับอะไร
การที่สิ่งที่เคยเป็นปริภูมิ n มิติต้องใช้พจน์ได้มากถึง
2^nก็รู้สึกจัดการยากมันน่าจะช่วยจัดการเรขาคณิต หรือก็คือผลคูณภายในได้ดีกว่านี้ แต่ผมยังไม่เคยเห็นคำอธิบายที่ทำให้เชื่อได้ว่าทำไมถึงใช้แค่ผลคูณลิ่มกับ ตัวดำเนินการดาว Hodge หรือ musical isomorphism ไม่ได้
สิ่งที่เหมือน “เวทมนตร์” อย่างการเปลี่ยนไบเวกเตอร์
u^vให้เป็นการหมุนในระนาบนั้นe^(u^v)tโดยเนื้อแท้แล้วก็คือการใช้ musical isomorphism เปลี่ยน 2-formu^vให้เป็น automorphism เชิงเส้น แล้วทำให้เข้าใจe^(u^v)tเป็นเลขชี้กำลังของเมทริกซ์อีกตัวอย่างที่ยกกันบ่อยคือทำให้สมการ Maxwell กลายเป็นสมการเดียวได้ แต่ถ้าใช้ differential forms ก็สรุปได้อยู่แล้วเป็นสองสมการที่เป็นจริงด้วยเหตุผลต่างกัน ผมเลยไม่เข้าใจประโยชน์ของการรวมมันเป็นสมการเดียว
2^n” บางครั้งการประหยัดนั้นเป็นเพียงภาพลวงตาตัวอย่างเช่น เวกเตอร์ปกติแปลงต่างจากเวกเตอร์ตำแหน่ง เราอาจแทนทั้งสองด้วยโครงสร้างข้อมูลเดียวกันได้ แต่ก็ต้องคอยติดตามว่าข้างในเป็นเวกเตอร์ชนิดใด และต้องใส่กรณีพิเศษที่จัดการต่างกันไว้ทั่วโค้ด
พีชคณิตเชิงเรขาคณิตเผชิญเรื่องนี้ตรง ๆ โดยใช้ฐาน
(i,j,k)สำหรับเวกเตอร์ และใช้ฐานแยกต่างหาก(j*k, k*i, i*j)สำหรับชนิดอื่นในแง่ที่ว่าสมการเดียวดีกว่าสองหรือสี่ นี่จึงเป็นตัวอย่างที่ดีว่าปริภูมิมิติสูงกว่ากลับประหยัดด้านการจัดเก็บมากกว่ามิติต่ำกว่าได้
สนามไฟฟ้าแตกต่างจากสนามแม่เหล็กค่อนข้างคล้ายกับที่เวกเตอร์แตกต่างจากไบเวกเตอร์ จะจัดการสนามไฟฟ้าและสนามแม่เหล็กเป็นสมการแยกแบบเฉพาะกรณีก็ได้ หรือจะจัดการอย่างสม่ำเสมอด้วยวิธีเดียวก็ได้
ควอเทอร์เนียนที่
w=1, x,y,z=0คือเอกลักษณ์ ส่วนควอเทอร์เนียนอย่างw=0, x=1หรือw=0, x=y=0.7สอดคล้องกับการหมุน 180 องศาเท่านั้นถ้าต้องการการหมุนใด ๆ ก็ต้องใช้การผสมของสองอย่างนี้ คือผสม “การหมุน 180 องศารอบเส้นนี้เล็กน้อย” กับ “การหมุน 0 องศา/เอกลักษณ์เล็กน้อย” การมีทั้งสเกลาร์และไบเวกเตอร์อยู่ด้วยกันหมายถึงสิ่งนี้เอง
ถ้าพยายาม “ระวัง” ด้วยผลคูณลิ่มและผลคูณภายในเพื่อหลีกเลี่ยงการผสม แปลว่าใช้ผิดแล้ว ผลคูณเชิงเรขาคณิต คือพระเอก และมันสร้างการผสมที่ยอดเยี่ยมมาก
ตัวอย่างเช่น ถ้าจัดการกับเวกเตอร์ปกติ ก็ต้องติดตามปริภูมิ n มิติอย่างน้อยสองชุดที่แปลงต่างกันพอสมควร
การแทนจุด ระนาบ เส้น เวกเตอร์ปกติ การเลื่อนขนาน และการหมุนทั้งหมดด้วยชนิด multivector เดียวและกฎที่สอดคล้องกันนั้น เมื่อเข้าใจแล้วค่อนข้างรู้สึกปลดปล่อยมาก แม้ผมเองก็ยังอยู่ระหว่างเรียนรู้ก็ตาม
การ interpolation ของแอนิเมชันด้านล่างเจ๋งจริง ๆ แต่ผมรู้สึกว่าโมเดลในส่วนอื่นของหน้าเว็บน่าจะ คึกคักน้อยลง หน่อย
คณิตศาสตร์ก็ยากพออยู่แล้วโดยไม่ต้องมีลูกช้างเชียร์ลีดเดอร์
ถ้าผู้เขียนเห็นอยู่ อยากให้ช่วยนิยามตัวย่อ PGA ตอนใช้ครั้งแรกด้วย
มันเพิ่มเวกเตอร์ฐานศูนย์เข้าไปหนึ่งตัวในเวกเตอร์ฐานของปริภูมิที่กำลังทำงานอยู่ วิธีนี้ทำให้แทนวัตถุเรขาคณิตที่ไม่ผ่านจุดกำเนิดด้วยพีชคณิตได้
อัลกอริทึมแบบนี้มีประสิทธิภาพไหมเมื่อคำนึงถึง GPU?
ผมมีภาพจำลาง ๆ ว่า GPU เหมาะกับงานเมทริกซ์ เลยสงสัยว่าถ้าใช้การวางรูปแบบด้วยพีชคณิตเชิงเรขาคณิต จะเสียข้อได้เปรียบนั้นไปจนในทางปฏิบัติไม่ได้ดีกว่าหรือเปล่า
เป็นการเดาแบบไม่ค่อยรู้ ถ้าผิดก็ช่วยแก้ให้ด้วย
จริง ๆ แล้วทั้ง shader core ก็เป็น SIMD อยู่แล้ว จึงไม่จำเป็นว่าจะทำแบบนั้นได้เสมอไป GPU บางรุ่นทำ บางรุ่นก็ไม่ทำ
PGA มีภาระในการทำความเข้าใจไม่น้อย แต่เป็นวิธีที่ดีมากสำหรับจัดการข้อแรก ยังไงก็ตาม ปกติแล้วควรลองวิธีที่ง่ายที่สุดและนำไปใช้จริงง่ายที่สุดก่อน
การนำไปใช้ที่ได้จากการแก้ข้อแรกด้วย PGA นั้นเพียงพอสำหรับทำต้นแบบส่วนที่เหลือของโปรแกรมและเบนช์มาร์กเพื่อหาคอขวดที่แท้จริง โชคดีที่ในกรณีส่วนใหญ่ มันมักเป็นวิธีคำนวณที่เร็วที่สุด หรือเร็วพอจนไม่กลายเป็นคอขวด
ต่อให้กลายเป็นคอขวด มันก็ทำให้เข้าใจปัญหาที่กำลังแก้อย่างลึกซึ้ง ผมคิดว่าควรมีความเข้าใจแบบนั้นก่อนเริ่มไล่บีบ cycle ด้วยความหวังว่าจะเร็วพอ
นี่ดูเหมือนการถกเถียงความต่างเล็ก ๆ น้อย ๆ ที่ปลายสุดของความก้าวหน้า
การที่แอนิเมชันโครงกระดูก 3D ยังใช้ เมทริกซ์ 4x4 บน GPU หมายความว่าคณิตศาสตร์ที่พัฒนาขึ้นเพื่อจุดประสงค์นี้บน CPU ในยุคประมาณ Half-Life 1 ยังคงอยู่แนวหน้า ตั้งแต่ปี 1998 ถึง 2024 ก็ 26 ปีแล้ว
อีก 1,000 ปีข้างหน้า แอนิเมชัน 3D ก็คงยังเหมือนเดิม
บทความนี้เกินขอบเขตความเข้าใจของผม แต่ชื่อเรื่องทำให้นึกถึงการทดลองที่เคยทำ เรนเดอเรอร์ 3D ง่าย ๆ
หลังจากพยายามเรียนพีชคณิตเชิงเส้นแล้วล้มเหลวหลายครั้ง ตอนอาบน้ำผมก็นึกขึ้นได้ว่าการหมุน 3D ก็แค่การหมุน 2D สามครั้ง และอันนั้นผมรู้อยู่แล้ว ประมาณหนึ่งชั่วโมงต่อมาก็ได้เรนเดอเรอร์ 3D แบบ wireframe ที่มี perspective ด้วย
แนะนำให้ทุกคนลองทำดู