OpenGL: ปรับขนาดจอแสดงผลและ glOrtho / glViewport


16

ฉันได้ค้นคว้าคำถามนี้จากหลาย ๆ แหล่งและยังไม่พบคำตอบที่แน่นอนที่บอกว่า "ใช่นั่นคือการคิดที่ถูกต้อง" หรือ "ไม่นี่คือวิธีที่ทำ"

ฉันพยายามรับประกันความเป็นอิสระในการแก้ปัญหาด้วยการเรนเดอร์ OpenGL วิธีที่ฉันคิดว่าฉันควรทำคือการสร้างการฉายภาพโดยใช้glOrthoทุกสิ่งที่ฉันต้องการให้พิกัดโลกเป็น ตัวอย่างเช่นglOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0). ถัดไปตั้งค่าวิวพอร์ตไปยังความละเอียดหน้าจอคือ glViewport(0, 0, 800, 600)- ในที่สุดเมื่อใดก็ตามที่หน้าต่างมีขนาดใหม่ให้ทำการโทรglViewportด้วยความละเอียดหน้าจอที่อัปเดต นี่จะเป็นการเพิ่มขนาดของคุณ

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

คิด?

คำตอบ:


20

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

อย่างไรก็ตามหากคุณไม่ทำอะไรมากกว่านี้คุณจะมีปัญหาอัตราส่วนภาพ ตัวอย่างเช่นให้ตัวเลขที่คุณเขียนถ้าคุณวาดวงกลมมันจะถูกบีบ - กว้างกว่าสูงเพราะขนาดแนวนอนของคุณคือ 800 / (50 + 50) = 8 และระดับแนวตั้งของคุณคือ 600 / (50+ 50) = 6

มีไม่สามารถจะแก้ปัญหาใด ๆ โดยอัตโนมัติเพื่อแก้ไขปัญหานี้ ; คุณจะต้องเลือกผลลัพธ์กราฟิกที่คุณต้องการและพิจารณาผลกระทบที่มีต่อการเล่นเกม ตัวอย่างทั่วไปบางส่วน:

  • ในมุมมองของการฉาย 3D เกมไม่มีฮัดที่เป็นวิธีง่ายๆปกติ (ใช้ได้ใน OpenGL เป็นส่วนหนึ่งของgluPerspective) คือการแก้ไขข้อมูลประมาณการของมุมมองเทียบกับแนวตั้ง ซึ่งหมายความว่าในเกมดังกล่าวหากคุณปรับขนาดหน้าต่างในแนวนอนคุณจะเห็นฉากมากหรือน้อยและส่วนตรงกลางของภาพจะไม่เปลี่ยนแปลงเลย

    แนวคิดเดียวกันนี้สามารถนำไปใช้กับมุมมอง 2D / 2.5D ได้เช่นกัน

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

  • หากคุณมีกราฟิกที่เติมวิวพอร์ตที่มีอัตราส่วนคงที่ (ตัวอย่างเช่นแผนที่ 2D แบบไม่เลื่อนหรือเส้นขอบตกแต่ง) หรือหากคุณไม่สามารถเปลี่ยนเค้าโครงได้คุณต้องทำบางอย่างเช่นมีแถบสีดำที่สอง ด้านข้างเพื่อเติมเต็มพื้นที่ที่ไม่ได้ใช้

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

  • หากคุณมี HUD ด้านบนของกราฟิกอื่น ๆ คุณสามารถตัดสินใจได้ว่าองค์ประกอบ HUD แต่ละรายการได้รับการแก้ไขเป็นส่วนหนึ่งของหน้าต่าง (ด้านบนซ้ายกลางด้านล่าง ฯลฯ ) และคำนวณพิกัดของมัน 'ยืด' ของอัตราส่วนที่แตกต่างกันจะได้รับการดูดซับโดย 'พื้นที่สีขาว' ระหว่างองค์ประกอบ HUD

width / heightในฐานะที่เป็นคณิตศาสตร์ที่เฉพาะเจาะจงของเรื่องที่ได้รับว่าคุณกำลังทำมติเป็นอิสระทั้งหมดที่คุณต้องเริ่มต้นด้วยเป็นอัตราส่วนจำนวนเดียว: ตัวอย่างเช่นถ้าหน้าต่างเป็นสี่เหลี่ยมมันจะเป็น 1 ถ้ามันคือ 800 คูณ 600 มันจะเท่ากับ 800/600 = 4/3 = 1.333̅

ตัวอย่างเช่นสมมติว่าคุณต้องการฉายภาพorthographic ที่คุณเขียนเพื่อเพิ่มพื้นที่บนด้านซ้ายและด้านขวาหากหน้าต่างกว้างขึ้น คุณสามารถทำสิ่งนี้ได้:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

สิ่งนี้รับประกันได้ว่าสำหรับหน้าต่างที่กว้างที่สุดเท่าที่สูงอย่างน้อยสิ่งที่คุณวาดด้วยพิกัด x และ y ที่มีค่า -50 ถึง 50 จะมองเห็นได้

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

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

โปรดทราบว่าในกรณีที่สองเราแบ่งมากกว่าคูณ นี้เป็นเพียงเพราะเราคำนวณอัตราส่วนเป็นwidth / heightมากกว่าheight / width; นำส่วนกลับมาใช้ถ้าคุณคิดว่าเข้าใจง่ายกว่า

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


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