เกม 2D และ OpenGL ที่ทันสมัย


10

Preconcepts

ตกลงดังนั้นสิ่งที่ฉันรวบรวมมาคือ:

  • อย่าใช้ไปป์ไลน์ที่คงที่ (เลิกใช้แล้วหรือกำลังจะเลิกใช้งาน)
  • vbos เก็บ "โมเดลวัตถุ" (n จุดสุดยอดข้อมูลส่วนใหญ่)
  • vaos อธิบายว่าข้อมูลถูกวางไว้อย่างไรเพื่อให้การโทรรู้ว่าส่วนใดของ vbo แต่ละชนิดสำหรับข้อมูลจุดยอด (หนึ่ง vao สามารถอ้างถึง vbos หลาย ๆ ตัวได้ตรงกันข้ามเป็นเรื่องยาก)
  • การเรียกแบบดึงแต่ละครั้งจะส่งข้อมูลจุดสุดยอดไปยังตัวแปลงข้อมูล

ฉันเห็น 3D (ไม่บังคับ)

จากข้อมูลเหล่านี้ฉันเห็นได้ว่าการวาดวัตถุที่ซับซ้อน 3D เป็นสิ่งที่ดีมาก ๆ ด้วย OpenGL ที่ทันสมัย โดยทั่วไปคุณจะโหลดโมเดลวัตถุ (อาจมาจาก Blender หรือซอฟต์แวร์ที่คล้ายคลึงกันอื่น ๆ ) ลงใน VBOs ที่มีพิกัดโลคัลและจากนั้นคุณเพียงแค่จัดหาพารามิเตอร์ shader ที่แตกต่างกัน (ออฟเซ็ต) ให้แต่ละอินสแตนซ์ของวัตถุ

ปัญหา / คำถาม

ในปัญหา 2D และลำดับความสำคัญแตกต่างกันอย่างสิ้นเชิงแม้ว่า คุณไม่ได้วาดวัตถุที่ซับซ้อนมากคุณไม่จำเป็นต้องใช้เมทริกซ์การฉายที่ซับซ้อน

อะไรจะเป็นวิธีที่ดีที่สุดในการวาดบ่อย ๆ (จริงๆแล้วโดยทั่วไปในทุกๆเฟรม) การเปลี่ยนรูปทรงเรขาคณิตด้วย OpenGL สมัยใหม่

ในย่อหน้าต่อไปนี้คุณสามารถเห็นแนวคิดของปัญหา (ปัญหาวงกลมและสี่เหลี่ยม) ที่ระบุการเปลี่ยนแปลงที่ฉันสนใจได้ดียิ่งขึ้น

ความพยายามของฉัน (ไม่จำเป็น)

ดังนั้นฉันเริ่มคิดว่าฉันจะจัดการกับการวาดรูปทรงเรขาคณิต 2D พื้นฐานบนหน้าจอได้อย่างไร:

  • สแควร์: โหลด[(1, 0), (1, 1), (0, 1), (0, 0)]VBO สำหรับรูปทรงเรขาคณิตของสแควร์ในพื้นที่ท้องถิ่นจากนั้นให้ความกว้างที่แท้จริงของสแควร์และพิกัดโลกและข้อมูลสี

เย็นดูง่าย ลองย้ายไปที่แวดวง:

  • วงกลม: พัดลมสามเหลี่ยมพร้อม ... เอ๊ะ ความแม่นยำเท่าไหร่ (จำนวนจุดยอด)? สำหรับวงกลมขนาดเล็กที่มีความแม่นยำต้องมีขนาดเล็กและสำหรับวงกลมที่มีความแม่นยำจะต้องสูง การโหลดอย่างชัดเจน 1 VBO อาจไม่เหมาะกับทุกกรณี ถ้าฉันต้องการเพิ่มความแม่นยำเพราะวงกลมถูกปรับขนาดให้ใหญ่ขึ้น

เท่ห์กว่าเดิม ให้ย้ายไปยังบางสิ่งที่ง่ายขึ้นเล็กน้อยสี่เหลี่ยมผืนผ้า

  • สี่เหลี่ยมผืนผ้า: เอ๊ะ ไม่มี "เรขาคณิตรูปสี่เหลี่ยมผืนผ้าทั่วไป" คุณมีสัดส่วนความกว้าง / ความสูงและนั่นก็ แต่สี่เหลี่ยมผืนผ้าแต่ละอันอาจแตกต่างกันไปหากขนาดมีการเปลี่ยนแปลง

อย่างที่คุณเห็นสิ่งต่าง ๆ ตกต่ำจากที่นั่น โดยเฉพาะกับรูปหลายเหลี่ยมที่ซับซ้อนและอะไรก็ตาม

ไม่มีนโยบายรหัส: P

ฉันต้องการภาพรวมของแนวคิดไม่จำเป็นต้องใช้รหัสโดยเฉพาะอย่างยิ่งรหัส C หรือ C ++ เพียงแค่พูดสิ่งที่ชอบ: "ทำ VBO ด้วยข้อมูลจุดสุดยอดนี้แล้วผูกมัน ... "


ฉันคิดว่าฉันเข้าใจสิ่งที่คุณถาม แต่คุณอาจต้องการให้คำถามนี้มีทิศทางที่มากขึ้น มันค่อนข้างชัดเจนว่าสิ่งที่ถูกถาม - ซึ่งเป็นเหตุผลที่ใกล้ชิด
Lysol

@AidanMueller ฉันไม่แน่ใจว่าสิ่งที่คุณหมายถึง แต่อย่าลังเลที่จะให้ทิศทางมากขึ้นถ้าคุณรู้สึกต้องการ
รองเท้า

คำตอบยอดนิยมในขณะนี้เริ่มต้นด้วยการพูดว่า "คำถามหลักของคุณน่าจะเป็น" นั่นแสดงว่ามันไม่ชัดเจนในสิ่งที่คุณถาม บางทีคุณควรสรุปสิ่งที่คุณไม่จำเป็นต้องรู้ในตอนท้ายของคำถาม นี่คือ Q / A หลังจากทั้งหมดไม่ใช่การสนทนา
Lysol

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

คุณสามารถวาดวงกลมที่แม่นยำด้วย shader ส่วน
user253751

คำตอบ:


5

คำถามหลักของคุณน่าจะเป็น:

อะไรจะเป็นวิธีที่ดีที่สุดในการวาดบ่อย ๆ (จริงๆแล้วโดยทั่วไปในทุกๆเฟรม) การเปลี่ยนรูปทรงเรขาคณิตด้วย OpenGL สมัยใหม่

ในวิธีส่วนใหญ่ไม่มีความแตกต่างใหญ่ระหว่าง 2d และ 3d OpenGL ไปป์ไลน์กราฟิกนั้นมีพิกัดพิเศษหนึ่งค่าซึ่งจะไม่ถูกนำมาใช้ในรูปแบบ 2d แต่มันเกี่ยวกับมัน

มีสองสามวิธีในการเปลี่ยนรูปทรงเรขาคณิตในแต่ละรูปวาด

  • คุณสามารถผลักจุดสุดยอดที่ CPU จัดเตรียมไว้ให้ทุกเฟรม (ดู/programming/14155615/opengl-updating-vertex-buffer-with-glbufferdataเพื่อดูหมายเหตุเกี่ยวกับการใช้บัฟเฟอร์ซ้ำ)

  • glDrawArrays(mode, first, count)คุณสามารถวาดส่วนที่แตกต่างกันของบัฟเฟอร์ที่มีอยู่ด้วย หากภาพเคลื่อนไหวลูปบางทีคุณสามารถใส่เฟรมที่กำหนดไว้ล่วงหน้าด้วยรายการจุดสุดยอดที่แตกต่างกันในบัฟเฟอร์ขนาดใหญ่และวาดส่วนที่เหมาะสมของบัฟเฟอร์แต่ละเฟรม

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

  • หากคุณมีเรขาคณิตที่เหมือนกันหลายอินสแตนซ์ (อาจได้รับอิทธิพลจากแอตทริบิวต์) glDrawElementsInstanced()อาจมีประโยชน์

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

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

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

คำถามอื่นของคุณถอดความ "วิธีที่ดีในการวาดวงกลมและสี่เหลี่ยมคืออะไร"

แวดวง

  • ด้วยเฉดสี tessellation (หรือเฉดสีเรขาคณิต) คุณสามารถทำให้รูปทรงเรขาคณิตของคุณเป็นแบบไดนามิก

  • คุณสามารถวาดสี่เหลี่ยมและในส่วนของคุณ shader ทึบแสงเท่านั้น (alpha = 1.0) ภายในรัศมีและโปร่งใส (alpha = 0.0) นอกรัศมี จากนั้นพิกเซลก็สมบูรณ์แบบทุกครั้ง (ทำให้จุดยอดที่เป็นรูปสี่เหลี่ยมจัตุรัสของคุณ -1 ถึง +1 และในส่วนที่แตกเป็นส่วน ๆ อย่างเช่น, outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;. สามารถทำให้ขอบเรียบขึ้นเล็กน้อยจะดูดีที่นั่น ... )

  • คุณสามารถใช้พูดพัดลมที่เป็นรูปสามเหลี่ยมได้ตลอดเวลา น่าจะดีพอ

รูปสี่เหลี่ยม

  • ฉันคิดว่าคุณตอบคำถามของคุณเองในคำถามนั้น สิ่งที่คุณแนะนำจะทำงานได้ดี!

ขอบคุณสำหรับชิ้นส่วน shader / radius สำหรับฉันที่ตอบคำถามของฉันฉันไม่คิดว่าฉันเข้าใจสิ่งที่คุณหมายถึง
รองเท้า

โอ้เช่นเดียวกับตารางคุณพูดถึงการควบคุมความกว้าง (กับชุดฉันถือว่า) และคุณเขียนว่า "คุณมีสัดส่วนความกว้าง / ความสูงและที่มัน แต่มันแต่ละรูปสี่เหลี่ยมผืนผ้าอาจแตกต่างกันถ้าขนาดมีการเปลี่ยนแปลง" . ดังนั้นสำหรับสี่เหลี่ยมให้ทำเช่นเดียวกับสี่เหลี่ยมจัตุรัส แต่คุณจะต้องมี 4 ค่า (x, y, w, h) แทน 3 (x, y, w) หรือผ่านใน (xlow, xhigh, ylow, yhigh) เป็นเครื่องแบบสี่ชุด ด้วยอินพุต (0,0) ถึง (1,1) ของคุณนั่นก็เพียงพอแล้วสำหรับ Vertex Shader ที่จะทำสิ่งที่ต้องการ
david van brink

โอ้ฉันเข้าใจแล้ว
รองเท้า

มีพัดลมอัตโนมัติใน GL ที่ทันสมัยเช่น GL_TRIANGLE_FAN จากไปป์ไลน์ฟังก์ชั่นคงที่หรือไม่
John P

5

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

1) สี่เหลี่ยมและสี่เหลี่ยมค่อนข้างง่าย ฉันมีกล่อง 1x1 เดียวใน VBO ซึ่งฉันใช้เพื่อทำให้ทุกอย่างกลมกลืน ฉันส่งเมทริกซ์ MVP ไปยัง shader ด้วย "กล่องหน่วย" นี้และฉันได้รวมเข้ากับสเกลเพิ่มเติมเพื่อปรับขนาดกล่องเป็นขนาดที่เหมาะสม - อย่างที่คุณรู้คุณสามารถมีขนาด x และ y ที่แตกต่างกัน

เพื่อจุดประสงค์ของฉันฉันกำลังคิดที่จะย้ายจากการใช้ "กล่องหน่วย" ไปยังเอนจิ้นอนุภาคบางอย่างเพื่อสไปรต์ 2D แต่นั่นเป็นอีกเรื่องหนึ่ง

2) ฉันไม่ได้ทำงานกับแวดวงมากนักฉันแค่ใช้ VBO แบบคงที่พร้อมจำนวนจุดยอดเฉพาะ แต่ฉันสามารถจินตนาการได้ว่าฉันสามารถทำให้การปรับเปลี่ยนบางอย่างมีผลต่อจำนวนจุดยอดที่วาดสำหรับวงกลม

เมื่อเชื่อมต่อข้อมูล VBO กับแอ็ตทริบิวต์ shader ฉันใช้ glVertexAttribPointer มันมีพารามิเตอร์ stride ตั้งใจที่จะใช้สำหรับข้อมูล interleaved (ที่ฉันใช้) แต่อาจเป็นไปได้ที่จะใช้เช่นนี้:

glVertexAttribPointer(..., n * sizeof(VERTEX_DATA), ...);

... เพื่อเลือกจุดสุดยอดทุก ๆ อันจากบัฟเฟอร์ดังนั้นส่งผลต่อจำนวนจุดยอดที่วาดสำหรับวงกลม ฉันสามารถสร้าง VAO หลายอันที่มี VBO เดียวกันกับก้าวที่แตกต่างกันซึ่งมีผลต่อจำนวนจุดยอดที่วาดสำหรับวงกลม ฉันไม่ได้ลองคิดดู

โดยทั่วไปแล้วใช่การทำงานกับ VBOs และทำให้การปรับแต่งด้าน CPU ซับซ้อนขึ้นเล็กน้อยทำไมฉันได้ศึกษาสิ่งต่าง ๆ เพื่อทำการปรับแต่งที่ด้าน GPU (เงา) ยังตามบทความนี้การใช้ VBOs มีประสิทธิภาพมากขึ้นในฮาร์ดแวร์ที่ทันสมัยแม้ว่าคุณจะต้อง "แทรกแซง" ด้าน CPU มาก:

http://www.quelsolaar.com/opengl_performance.txt

หวังว่านี่จะช่วยคุณในการออกแบบและตัดสินใจเส้นทางของคุณ


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