ฉันจะงอวัตถุใน OpenGL ได้อย่างไร


11

มีวิธีหนึ่งที่สามารถโค้งงอวัตถุเช่นทรงกระบอกหรือระนาบโดยใช้ OpenGL ได้หรือไม่?

ฉันเป็นผู้เริ่มต้น OpenGL (ฉันใช้ OpenGL ES 2.0 ถ้าเป็นเรื่องสำคัญแม้ว่าฉันจะสงสัยว่าคณิตศาสตร์มีความสำคัญที่สุดในกรณีนี้ดังนั้นจึงเป็นเวอร์ชั่นที่ไม่ขึ้นอยู่กับรุ่น) ฉันเข้าใจพื้นฐาน: แปลหมุนหมุนเมทริกซ์เป็นต้น ฉันสงสัยว่ามีเทคนิคที่ช่วยให้คุณเปลี่ยนรูปทรงเรขาคณิตของวัตถุของคุณ (ในกรณีนี้ด้วยการดัดงอ) หรือไม่?

ยินดีต้อนรับลิงค์บทเรียนหรือการอ้างอิงอื่น ๆ !

คำตอบ:


11

สิ่งที่คุณต้องทำเพื่อ "โค้ง" วัตถุคือการใช้การผสมผสานที่เหมาะสมของการแปล / การหมุน / การปรับกับส่วนย่อยบางส่วนของจุดยอดของวัตถุที่มีปัญหา - อาจทำให้น้ำหนักการเปลี่ยนแปลงนั้นสอดคล้องกัน

การทำเช่นนี้เป็นแฟชั่นที่ดูดีน่าจะทำให้ต้องใช้จุดยอดมากเกินกว่าที่จะจำเป็นอย่างยิ่งในการอธิบายตาข่ายดั้งเดิม ตัวอย่างเช่นทรงกระบอกธรรมดาอาจมีจุดยอดที่ปลายทั้งสองด้าน แต่ถ้าคุณต้องการให้กระบอกนั้นงออยู่ตรงกลางคุณจะต้องมีจุดยอดเช่นกัน

หากสิ่งที่คุณสนใจมีความเฉพาะเจาะจงมากการเปลี่ยนรูปแบบครั้งเดียวของรูปร่างที่เรียบง่ายมาก (เช่นระนาบดังกล่าวข้างต้น) คุณอาจทำได้ด้วยตนเอง ตัวอย่างเช่นเลือก "โค้งแกน" สำหรับระนาบของคุณและคำนวณการแปลงที่เหมาะสมสำหรับแต่ละแถวของจุดยอดระนาบเพื่อให้เกิดการหมุนที่เหมาะสมเกี่ยวกับแกนโค้งนั้นขึ้นอยู่กับระยะห่างจากมันจากนั้นจึงนำไปใช้กับเรขาคณิต CPU อย่างตรงไปตรงมาที่สุดอย่างน้อยในตอนแรก) แต่เทคนิคดังกล่าวจะไม่ขยายขนาดและน่าเบื่อมาก

เพราะมันสามารถทำให้ยุ่งยากในการได้อย่างถูกต้องคิดออกว่าจะมีน้ำหนักเปลี่ยนแปลงไปในแต่ละจุดสุดยอดของแต่ละบุคคลในชุดเพื่อให้บรรลุความผิดปกติที่ต้องการ (โดยเฉพาะอย่างยิ่งสำหรับวัตถุในทางปฏิบัติมากขึ้นและซับซ้อน), เกมจำนวนมากใช้เทคนิคที่เรียกว่าแอนิเมชั่โครงกระดูก ในระดับสูงสิ่งนี้เกี่ยวข้องกับการเชื่อมโยงชุดเรขาคณิตแยกต่างหาก ("โครงกระดูก") กับตาข่ายของคุณ รูปทรงเรขาคณิตนั้นแสดงถึงกระดูกของวัตถุของคุณและคุณกำหนด (บ่อยครั้งในเครื่องมือสร้างแบบจำลอง) การทำแผนที่ระหว่างจุดยอดของแบบจำลองจริงและกระดูกของโครงกระดูก - ซึ่งกระดูกเกี่ยวข้องกับแต่ละจุดยอดและกระดูกมีผลกระทบต่อความผิดปกติอย่างไร ของจุดสุดยอดนั้น จากนั้นโครงกระดูกจะเคลื่อนไหวโดยตรงและภาพเคลื่อนไหวจะถูกถ่ายโอนไปยังแบบจำลองจริงผ่านความสัมพันธ์ระหว่างกระดูกและจุดยอด

โดยทั่วไปแล้วในเทคนิคนี้การทำแผนที่ระหว่างโครงกระดูกและตาข่ายจริงถูกกำหนดในเวลาการผลิตสินทรัพย์ ภาพเคลื่อนไหวสามารถสร้างได้ในตอนนั้นหรือสามารถสร้างขั้นตอนตอนรันไทม์ได้ แอปพลิเคชั่นของการแปลงภาพเคลื่อนไหวเป็นตาข่ายจริงเกิดขึ้นที่รันไทม์ โดยทั่วไปจะไม่มีการสร้างจุดยอดใหม่ที่รันไทม์ซึ่งหมายความว่าช่วงของการเสียรูปทรงที่ดูดีจะได้รับการแก้ไขโดยปริยายในตาข่ายเมื่อมันถูกสร้างขึ้นในตอนแรก

ในทางทฤษฎีเราสามารถประยุกต์ใช้ tessellation และส่วนย่อยของ mesh ที่ runtime โดยอาศัยการวิเคราะห์การแปลงในภาพเคลื่อนไหวและทำให้เกิดจุดยอดที่เหมาะสมในการสร้างภาพเคลื่อนไหวที่ไม่จำเป็นต้องมีการวางแผน ฉันไม่ได้ตระหนักถึงเอกสารใด ๆ ที่เกี่ยวข้องกับเรื่องนี้ในทันที

ดูสิ่งนี้ด้วย:


9

สำหรับคณิตศาสตร์การแปรปรวนที่เกิดขึ้นจริงสิ่งนี้อาจซับซ้อนมากทำไมคุณไม่เริ่มที่นี่ .

ตอนนี้ฉันจะพูดเกี่ยวกับวิธีการที่คุณสามารถนำไปใช้นี้สมมติว่าคุณมีคณิตศาสตร์อยู่แล้วสำหรับวิธีที่คุณจะทำให้การเสียรูปของคุณ

2 วิธี:

1) ทุกเฟรมเยี่ยมชมทุกจุดยอดในรูปแบบกระบอกสูบและชดเชยด้วยวิธีใดวิธีหนึ่ง

2) ชดเชยจุดยอดในส่วนยอดขณะที่คุณกำลังแสดงผล OpenGL ES 2.0 รองรับเครื่องแปลงยอด ดังนั้นคุณจะโชคดี

คุณต้องการที่จะวาร์ปวัตถุตามที่ปรากฏบนหน้าจอหรือคุณต้องการที่จะวาร์ปวัตถุเพื่อให้ทุกวัตถุในเกมรู้ว่ามันได้รับการเปลี่ยนรูป?

หากคุณวิปริตวัตถุใน Shader จุดสุดยอดที่แล้วที่เกิดขึ้นเฉพาะในทันทีก่อนที่จะแสดงผล / แรสเตอร์ดังนั้นนี้หมายความว่าไม่มีวัตถุเกมจะรู้เกี่ยวกับการเสียรูป นี่เป็นเรื่องปกติถ้าคุณเพียงแค่สร้างโปรแกรมรักษาหน้าจอหรือหากการเปลี่ยนรูปมีขนาดเล็กมากจนไม่มีผลกระทบกับรูปร่างของวัตถุ

เมื่อคุณบิดรูปทรงเรขาคณิตในส่วนShader ที่ จุดที่เดิมของรุ่นจริงไม่ย้าย (พวกเขาเท่านั้นที่ปรากฏจะย้าย )

ความผิดปกติใน Shader ที่

undeformed:

ไม่ผิดรูป

พิการ

พิการ

นี่คือจากบทที่ 6 ของการสอน cg (โปรแกรม # 14)

รหัส shader เพื่อสร้างความผิดปกตินี้เป็นสิ่งที่ต้องการ

// choose a displacement amount
float displacement = scaleFactor * 0.5 * sin(position.y * frequency * time) + 1 ;

// displace it in the direction of the normal
float4 displacementDirection = float4(normal.x, normal.y, normal.z, 0) ;

// move the vertex
float4 newPosition = position + displacement * displacementDirection ;

// transform (as normal)
oPosition = mul(modelViewProj, newPosition) ;

ดังนั้นคุณสามารถเห็นสิ่งนี้เกิดขึ้นแสดงก่อนที่จะเกิดขึ้น (จุดสุดยอด shader เกิดขึ้นบน GPU) ดังนั้นรหัสซีพียูจึงไม่มีทางเข้าถึงตำแหน่งเวอร์เท็กซ์ที่แปลงสภาพ (มีวิธีส่งข้อมูลจาก GPU ไปยัง CPU (โดยหลักผ่านพื้นผิว) จะไม่ไปที่นั่น)


8

สิ่งที่คุณพยายามทำให้สำเร็จนั้นเป็นส่วนย่อยของหัวข้อการเปลี่ยนรูปแบบตาข่าย แต่เนื่องจากคุณเป็นคนขอทานฉันเกรงว่าข้อมูลประเภทนี้อาจจะแปลกไปหน่อยในตอนนี้ ฉันจะพยายามวางแนวคิดพื้นฐานไว้

ในการทำสิ่งนี้คุณต้องมีสองสิ่ง:

  1. ตาข่ายของคุณต้องมีจุดยอดพอให้คุณแปลง ตัวอย่างเช่นถ้ามันเป็นเครื่องบินคุณจะต้องตรวจสอบให้แน่ใจว่ามันถูกสร้างขึ้นมาเป็นกริดโดยมีจุดยอดต่าง ๆ เพื่อให้คุณเปลี่ยนรูป สิ่งเดียวกันกับกระบอก อาจเป็นไปได้ที่จะบรรลุสิ่งนี้ในขณะทำงานด้วย tessellation แต่ฉันไม่รู้เกี่ยวกับหัวเรื่องมากนัก
  2. คุณต้องใช้ Shader ที่จุดยอดเพื่อทำให้จุดยอด โดยพื้นฐานแล้วเครื่อง Shader ที่ดูแลการคำนวณตำแหน่งที่แปลงสุดท้ายของแต่ละจุดสุดยอดดังนั้นคุณสามารถใช้โอกาสในการเปลี่ยนรูปแบบใด ๆ กับพวกเขา

ฉันไม่แน่ใจว่ามันจะมีประโยชน์เพียงใด แต่ลองดูที่ทรัพยากร OpenGL นี้เพราะมันดูเหมือนจะเป็นสิ่งที่คุณต้องการ:

http://www.ozone3d.net/tutorials/mesh_deformer_p3.php#part_3

ภาพหน้าจอจากลิงก์นั้น:

ป้อนคำอธิบายรูปภาพที่นี่

แก้ไข

เพิ่งเห็นคำตอบของ Josh และฉันเห็นด้วยภาพเคลื่อนไหวโครงกระดูกเป็นวิธีที่สง่างามมากในการสรุปปัญหานี้โดยเฉพาะอย่างยิ่งเมื่อความผิดปกติของคุณเริ่มซับซ้อนและยากที่จะเป็นตัวแทนทางคณิตศาสตร์

แต่โปรดจำไว้ว่าทั้งสองจุดข้างบนยังคงใช้อยู่ - คุณทำได้เพียงทำให้พิการจุดยอดดังนั้นเห็นได้ชัดว่าพวกเขาจำเป็นต้องมีอยู่ในตอนแรกซึ่งเป็นสาเหตุที่ตาข่ายของคุณต้องการความหนาแน่นของจุดยอดที่เหมาะสม และโดยปกติแล้วมันคือจุดสุดยอดที่ขับเคลื่อนภาพเคลื่อนไหวโครงกระดูก

และโดยวิธีการที่คุณสามารถทำสิ่งเหล่านี้บน CPU ด้วย แต่ทุกวันนี้มันเป็นตัวเลือกที่ดีกว่าในการทำ GPU ซึ่งเป็นสาเหตุที่ฉันให้ความสำคัญกับ Shader ที่ยอดเยี่ยมและคุณควรมองมัน มันไม่ใช่โปรแกรมที่ยากกว่าการทำบน CPU เลย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.