OpenGL เชิงวัตถุ


12

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

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


1
มีเกมโอเพนซอร์ซที่นั่นรวมถึงบทแนะนำที่มีขนาดใหญ่กว่า ลองใช้งานบางส่วนเพื่อดูว่ามีการจัดระเบียบอย่างไร
MichaelHouse

คุณเป็นผู้เริ่มต้นเมื่อพูดถึงการเรนเดอร์เอ็นจิ้น?
Samaursa

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

1
@ ซัลลิแวน: "ฉันคิดว่าแนวคิดแบบนี้จะใช้กับเกมเกือบทุกเกม" พวกเขาทำไม่ได้ หากคุณขอให้ฉันสร้าง Tetris ฉันจะไม่ยุ่งกับการทำเลเยอร์เสื้อคลุมขนาดใหญ่หรือบางสิ่งรอบ ๆ OpenGL เพียงใช้มันโดยตรง หากคุณขอให้ฉันทำอะไรบางอย่างเช่น Mass Effect เราจะต้องมีสิ่งที่เป็นนามธรรมหลายชั้นรอบ ๆ ระบบการเรนเดอร์ของเรา การโยนเอนจิน Unreal ที่ Tetris กำลังใช้ปืนลูกซองเพื่อไล่แมลงวัน มันทำให้งานหนักกว่าแค่เขียนโค้ดโดยตรง คุณควรสร้างระบบที่ใหญ่และซับซ้อนเท่าที่คุณต้องการและไม่ใหญ่กว่า
Nicol Bolas

1
@Sullivan: ความซับซ้อนเพียงอย่างเดียวที่คำถามของคุณบอกไว้คือที่ที่คุณพูดถึงการแยกไฟล์หลาย ๆ ไฟล์ ซึ่งเป็นสิ่งที่ฉันจะทำแม้กระทั่งใน Tetris และมีความซับซ้อนหลายระดับระหว่าง Tetris และเอนจิน Unreal ดังนั้นอีกครั้ง: คุณถามเรื่องอะไร
Nicol Bolas

คำตอบ:


6

ฉันคิดว่า OO OpenGL นั้นไม่จำเป็น มันแตกต่างกันเมื่อคุณพูดถึง shader, model, etc class

โดยทั่วไปคุณจะต้องเริ่มต้นเกม / เครื่องมือก่อน (และสิ่งอื่น ๆ ) จากนั้นคุณจะโหลดพื้นผิวแบบจำลองและเฉดสีไปยัง RAM (หากจำเป็น) และวัตถุบัฟเฟอร์และอัปโหลด / รวบรวมเฉดสี หลังจากนั้นคุณในโครงสร้างข้อมูลหรือระดับชั้นของคุณ Shader รุ่นมีintรหัสของเฉดสี, รุ่นและวัตถุพื้นผิวบัฟเฟอร์

ฉันคิดว่าเอ็นจิ้นส่วนใหญ่มีส่วนประกอบเครื่องยนต์และทุกคนมีอินเทอร์เฟซบางอย่าง เอ็นจิ้นทั้งหมดที่ฉันได้ดูมีส่วนประกอบบางอย่างเช่น Renderer หรือSceneManagerหรือทั้งสองอย่าง (ขึ้นอยู่กับความซับซ้อนของเกม / เอ็นจิ้น ) กว่าที่คุณจะมีคลาสOpenGLRendererและ / หรือ DXRenderer ซึ่งใช้อินเตอร์เฟส Renderer จากนั้นถ้าคุณมีSceneManagerและRendererคุณสามารถทำสิ่งต่อไปนี้:

  • Traverse SceneManagerและส่งแต่ละวัตถุไปยังRendererเพื่อการเรนเดอร์
  • ห่อหุ้มตัวพิมพ์ใหญ่ในบางวิธีของSceneManager
  • ส่งSceneManagerไปยังRendererเพื่อจัดการ

Renderer อาจเรียกฟังก์ชั่นการดึงของวัตถุซึ่งจะเรียกใช้ฟังก์ชันการดึงของแต่ละตาข่ายที่ประกอบด้วยและตาข่ายจะผูกวัตถุพื้นผิวผูก shader เรียกใช้ฟังก์ชั่นการวาด OpenGL จากนั้นใช้ shaders พื้นผิวและวัตถุบัฟเฟอร์ข้อมูลวัตถุ

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

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

ลองดูที่รายละเอียดเพิ่มเติมเกี่ยวกับเอ็นจิ้นเกมอื่น ๆ มีจำนวนมากและเอกสารประกอบของพวกเขาก็ค่อนข้างพร้อมใช้งาน

แต่ใช่คลาสทำให้ชีวิตง่ายขึ้น คุณควรใช้พวกเขาทั้งหมดและจดจำเกี่ยวกับการห่อหุ้มการสืบทอดอินเทอร์เฟซและสิ่งดีๆอื่น ๆ


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

วัตถุเป็นตัวอย่างของชั้นเรียนและ 'คุณควรใช้พวกเขาทั้งหมด'
edin-m

ขออภัยฉันตั้งใจถามว่า 'ฉันควรใช้วัตถุอย่างไร' ความผิดฉันเอง.
Sullivan

มันขึ้นอยู่กับการออกแบบชั้นเรียนของคุณ ตัวอย่างพื้นฐานบางอย่างจะเป็นสัญชาตญาณบางอย่างเช่น: object3d (class) มี meshes (class); แต่ละตาข่ายมีวัสดุ (ชั้น); วัสดุแต่ละอย่างมีพื้นผิว (สามารถเป็นคลาสหรือแค่ id) และ shader (คลาส) แต่เมื่อคุณอ่านเกี่ยวกับแต่ละองค์ประกอบคุณจะเห็นว่ามีวิธีการที่แตกต่างกัน แต่เท่าเทียมกันในการสร้าง SceneManager, Renderer, MemoryManager (ทั้งหมดนี้สามารถเป็นคลาสเดียวหรือหลาย ๆ องค์ประกอบสืบทอด ฯลฯ ) หนังสือหลายสิบเล่มถูกเขียนในหัวข้อนี้ (สถาปัตยกรรมเอ็นจิ้นเกม) และเพื่อตอบคำถามโดยละเอียดเราสามารถเขียนได้หนึ่งเล่ม
edin-m

ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุดที่ฉันจะได้รับ ขอบคุณสำหรับความช่วยเหลือของคุณ :)
ซัลลิแวน

2

OpenGL มีแนวคิด 'วัตถุ' อยู่แล้ว

ตัวอย่างเช่นสิ่งใดก็ตามที่มี ID สามารถผ่านเป็นวัตถุ (นอกจากนี้ยังมีสิ่งที่ชื่อ 'วัตถุ' โดยเฉพาะ) บัฟเฟอร์, พื้นผิว, วัตถุบัฟเฟอร์เท็กซ์, วัตถุอาเรย์เท็กซ์, วัตถุเฟรมบัฟเฟอร์และอื่น ๆ ด้วยการทำงานเล็ก ๆ น้อย ๆ คุณสามารถห่อคลาสเรียนรอบ ๆ พวกเขาได้ นอกจากนี้ยังช่วยให้คุณสามารถถอยกลับไปใช้ฟังก์ชั่น OpenGL เก่าที่เลิกใช้แล้วหากบริบทของคุณไม่สนับสนุนส่วนขยาย ตัวอย่างเช่น VertexBufferObject อาจถอยกลับไปใช้ glBegin (), glVertex3f () และอื่น ๆ

มีสองสามวิธีที่คุณอาจต้องย้ายออกจากแนวคิด OpenGL ดั้งเดิมตัวอย่างเช่นคุณอาจต้องการเก็บข้อมูลเมตาเกี่ยวกับบัฟเฟอร์ในวัตถุบัฟเฟอร์ ตัวอย่างเช่นถ้าบัฟเฟอร์เก็บจุดยอด รูปแบบของจุดยอดคืออะไร (เช่นตำแหน่ง, ปกติ, texcoords และอื่น ๆ ) สิ่งที่ดั้งเดิมใช้ (GL_TRIANGLES, GL_TRIANGLESTRIP, ฯลฯ ... ) ข้อมูลขนาด (จำนวนลอยถูกเก็บไว้จำนวนรูปสามเหลี่ยมที่พวกเขาเป็นตัวแทน ฯลฯ ... ) เพียงเพื่อทำให้ง่ายต่อการเสียบลงในคำสั่งวาดอาร์เรย์

ผมขอแนะนำให้คุณมองไปที่OGLplus มันคือการเชื่อม C ++ สำหรับ OpenGL

อีกทั้งglxxนั่นเป็นเพียงการโหลดส่วนขยายเท่านั้น

นอกเหนือจากการห่อ OpenGL API คุณควรดูที่การสร้างระดับหนึ่งที่สูงขึ้นเล็กน้อยจากด้านบน

ตัวอย่างเช่นคลาสตัวจัดการวัสดุที่รับผิดชอบการให้เฉดสีทั้งหมดของคุณโหลดและใช้งาน นอกจากนี้ยังจะต้องรับผิดชอบในการถ่ายโอนทรัพย์สินให้กับพวกเขา ด้วยวิธีนี้คุณสามารถโทรหา: materials.usePhong (); material.setTexture (sometexture); material.setColor () สิ่งนี้จะช่วยให้มีความยืดหยุ่นมากขึ้นเนื่องจากคุณสามารถใช้สิ่งใหม่กว่าเช่นวัตถุชุดบัฟเฟอร์ที่ใช้ร่วมกันเพื่อให้มีเพียง 1 บัฟเฟอร์ขนาดใหญ่ที่มีคุณสมบัติทั้งหมดที่ร่มเงาของคุณใช้ใน 1 บล็อก แต่ถ้ามันไม่สนับสนุนคุณ คุณสามารถมี shader เสาหินขนาดใหญ่ 1 อันและสลับระหว่างโมเดล shader ที่แตกต่างกันโดยใช้รูทีนที่สม่ำเสมอถ้ามันรองรับหรือคุณสามารถถอยกลับไปใช้ shader ขนาดเล็กหลาย ๆ อันได้

นอกจากนี้คุณยังสามารถดูรายละเอียดของ GLSL สำหรับการเขียนโค้ด shader ของคุณ ตัวอย่างเช่น #include จะมีประโยชน์อย่างเหลือเชื่อและใช้งานง่ายมากในโค้ดการโหลด shader ของคุณ (นอกจากนี้ยังมีส่วนขยาย ARBสำหรับมัน) นอกจากนี้คุณยังสามารถสร้างรหัสของคุณได้ทันทีตามส่วนขยายที่ได้รับการสนับสนุนตัวอย่างเช่นใช้วัตถุชุดที่ใช้ร่วมกันหรือถอยกลับไปใช้เครื่องแบบปกติ

ในที่สุดคุณจะต้องการ API การเรนเดอร์ระดับสูงที่ทำสิ่งต่าง ๆ เช่นกราฟฉาก, เอฟเฟกต์พิเศษ (เบลอ, เรืองแสง), สิ่งที่ต้องใช้การเรนเดอร์หลายครั้งเช่นเงาแสงและอื่น ๆ และนอกเหนือจากนั้น API เกมที่ไม่มีส่วนเกี่ยวข้องกับ API กราฟิก แต่เพียงเกี่ยวข้องกับวัตถุในโลก


2
"ฉันแนะนำให้คุณดูที่ OGLplus มันคือการผูก C ++ สำหรับ OpenGL" ฉันจะแนะนำกับว่า ฉันชอบ RAII แต่มันไม่เหมาะสมกับวัตถุ OpenGL เกือบทั้งหมด วัตถุ OpenGL เชื่อมโยงกับการสร้างทั่วโลก: บริบท OpenGL ดังนั้นคุณจะไม่สามารถสร้างวัตถุ C ++ เหล่านี้ได้จนกว่าคุณจะมีบริบทและคุณจะไม่สามารถลบวัตถุเหล่านี้หากบริบทนั้นถูกทำลายไปแล้ว นอกจากนี้ยังให้ภาพลวงตาที่คุณสามารถปรับเปลี่ยนวัตถุโดยไม่ต้องเปลี่ยนสถานะโลก นี่เป็นเรื่องโกหก (ยกเว้นว่าคุณกำลังใช้ EXT_DSA)
Nicol Bolas

@ NicolBolas: ฉันไม่สามารถตรวจสอบเพื่อดูว่ามีบริบทและเริ่มต้นเท่านั้นแล้ว? หรืออาจอนุญาตให้ผู้จัดการสร้างวัตถุที่ต้องใช้บริบท OpenGL เท่านั้น --- btw ชุดบทเรียนที่ยอดเยี่ยม (ลิงก์ในโปรไฟล์ของคุณ)! อย่างใดฉันไม่เคยเจอพวกเขาเมื่อค้นหา OpenGL / กราฟิก
Samaursa

@ Samaursa: ไปยังจุดสิ้นสุดอะไร หากคุณมีผู้จัดการสำหรับวัตถุ OpenGL ดังนั้น ... คุณไม่จำเป็นต้องให้วัตถุดูแลตัวเอง ผู้จัดการสามารถทำเพื่อพวกเขาได้ และถ้าคุณเริ่มต้นเมื่อบริบทมีอยู่จะเกิดอะไรขึ้นถ้าคุณพยายามใช้วัตถุที่ไม่ได้เริ่มต้นอย่างถูกต้อง? มันสร้างความอ่อนแอใน codebase ของคุณ และไม่เปลี่ยนแปลงสิ่งที่ฉันพูดเกี่ยวกับความสามารถในการปรับเปลี่ยนวัตถุเหล่านี้โดยไม่ต้องสัมผัสกับสถานะโลก
Nicol Bolas

@NicolBolas: "คุณจะไม่สามารถสร้างวัตถุ C ++ เหล่านี้จนกว่าคุณจะมีบริบท" ... มันแตกต่างจากการใช้โครงสร้าง OpenGL เปล่าหรือไม่? ในสายตาของฉันoglplus::Contextชั้นเรียนทำให้การพึ่งพานี้ปรากฏอย่างชัดเจน - นั่นจะเป็นปัญหาหรือไม่? ฉันเชื่อว่ามันจะช่วยผู้ใช้ OpenGL ใหม่ ๆ ให้หลีกเลี่ยงปัญหามากมาย
xtofl

1

ใน OpenGL สมัยใหม่คุณสามารถแยกวัตถุที่แสดงผลออกจากกันได้เกือบทั้งหมดโดยใช้โปรแกรม vaos และ shader ที่แตกต่างกัน และแม้แต่การนำวัตถุหนึ่งไปใช้ก็สามารถแยกออกเป็นเลเยอร์นามธรรมได้

ตัวอย่างเช่นหากคุณต้องการใช้ภูมิประเทศคุณสามารถกำหนด TerrainMesh ที่มีคอนสตรัคเตอร์สร้างจุดยอดและดัชนีสำหรับภูมิประเทศและตั้งค่าให้เป็นอาเรย์บัฟเฟอร์และถ้าคุณกำหนดตำแหน่งให้กับคุณลักษณะ ควรรู้วิธีการแสดงผลและควรระมัดระวังในการยกเลิกการเปลี่ยนแปลงบริบททั้งหมดที่ทำไว้เพื่อตั้งค่าการแสดงผล คลาสนี้ไม่ควรรู้อะไรเกี่ยวกับโปรแกรม shader ที่กำลังจะแสดงผลและไม่ควรรู้อะไรเกี่ยวกับวัตถุอื่น ๆ ในฉาก เหนือคลาสนี้คุณสามารถกำหนดภูมิประเทศซึ่งทราบรหัส shader และหน้าที่ของมันคือการสร้างการเชื่อมต่อระหว่าง shader และ TerrainMesh นี่ควรหมายถึงการรับแอตทริบิวต์และตำแหน่งที่เหมือนกันและการโหลดในพื้นผิวและสิ่งต่าง ๆ เช่นนั้น คลาสนี้ไม่ควรรู้อะไรเกี่ยวกับวิธีการใช้ภูมิประเทศสิ่งที่อัลกอริทึม LoD ใช้นั้นเป็นเพียงการรับผิดชอบในการแรเงาภูมิประเทศ ด้านบนนี้คุณสามารถกำหนดฟังก์ชั่นที่ไม่ใช่ OpenGL เช่นพฤติกรรมและการตรวจจับการชนและอื่น ๆ

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

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


0

ioDoom3 น่าจะเป็นจุดเริ่มต้นที่ยอดเยี่ยมเพราะคุณสามารถไว้ใจ Carmack เพื่อฝึกการเขียนโค้ดที่ยอดเยี่ยม นอกจากนี้ฉันเชื่อว่าเขาไม่ได้ใช้ megatexturing ใน Doom3 ดังนั้นจึงค่อนข้างตรงไปตรงมาเป็นเรนเดอร์เรต


6
"ในขณะที่คุณสามารถพึ่งพา Carmack เพื่อฝึกการเข้ารหัสที่ยอดเยี่ยม" โอ้มนุษย์นั่นเป็นสิ่งที่ดี Carmack ปฏิบัติตามวิธีการเข้ารหัส C ++ ที่ยอดเยี่ยม นั่นคือการจลาจล! โอ้ ... คุณไม่ได้ล้อเล่น อืม ... คุณเคยดูรหัสของเขาจริงเหรอ? เขาเป็นโปรแกรมเมอร์ซีและนั่นคือสิ่งที่เขาคิด ซึ่งเป็นที่ดีสำหรับ C แต่คำถามคือเกี่ยวกับC ++
Nicol Bolas

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