ऑब्जेक्ट-ओरिएंटेड ओपनजीएल


12

मैं कुछ समय से OpenGL का उपयोग कर रहा हूं और बड़ी संख्या में ट्यूटोरियल पढ़ चुका हूं। इस तथ्य के अलावा कि उनमें से बहुत से अभी भी तय पाइपलाइन का उपयोग करते हैं, वे आमतौर पर एक स्रोत फ़ाइल में सभी आरंभीकरण, राज्य परिवर्तन और ड्राइंग को फेंक देते हैं। यह एक ट्यूटोरियल के सीमित दायरे के लिए ठीक है, लेकिन मैं एक कठिन समय काम कर रहा हूं कि इसे पूर्ण गेम तक कैसे बढ़ाया जाए।

आप OpenGL के अपने उपयोग को फ़ाइलों में कैसे विभाजित करते हैं? वैचारिक रूप से, मैं कह सकता हूँ, एक प्रतिपादन वर्ग, विशुद्ध रूप से स्क्रीन के लिए सामान प्रदान करता है, लेकिन कैसे shaders और रोशनी की तरह काम करेगा? क्या मुझे रोशनी और शेड जैसी चीजों के लिए अलग-अलग कक्षाएं होनी चाहिए?


1
वहाँ खुले स्रोत के खेल के साथ-साथ बड़े ट्यूटोरियल हैं जिनके पास अधिक कोड हैं। उनमें से कुछ की जाँच करें और देखें कि कोड कैसे व्यवस्थित है।
MichaelHouse

जब आप इंजन प्रदान करने की बात करते हैं तो क्या आप एक शुरुआत हैं?
समौरसा

इस सवाल का दायरा कम होने के बिना यथोचित जवाब नहीं दिया जा सकता है। बस आप क्या बनाने की कोशिश कर रहे हैं? किस तरह का गेम, किस तरह का ग्राफिक्स है, आदि।
निकोल बोलस

1
@ सुलिवन: "मुझे लगा कि इस तरह की अवधारणा लगभग किसी भी खेल पर लागू होगी।" वे नहीं करते। यदि आप मुझे टेट्रिस बनाने के लिए कहते हैं, तो मैं एक बड़ी आवरण परत या ओपनगेल के आसपास कुछ बनाने से परेशान नहीं होगा। बस इसे सीधे उपयोग करें। यदि आप मुझसे मास इफ़ेक्ट जैसा कुछ बनाने के लिए कहते हैं, तो हमें अपने रेंडरिंग सिस्टम के आसपास एब्सट्रैक्शन की कई परतों की आवश्यकता होगी। टेट्रिस पर अवास्तविक इंजन को फेंकना मक्खियों का शिकार करने के लिए एक बन्दूक का उपयोग करना है; यह सीधे हाथ कोडिंग की तुलना में कार्य को इतना कठिन बना देता है। आपको केवल एक सिस्टम के बड़े और जटिल के रूप में निर्माण करना चाहिए जैसा कि आपको चाहिए , और कोई बड़ा नहीं।
निकोल बोलस

1
@ सुलिवान: आपके प्रश्न का अर्थ केवल जटिलता है जहां आप कई फाइलों में विभाजित होने की बात करते हैं। मैं टेट्रिस में भी ऐसा कुछ करूंगा। और टेट्रिस और अवास्तविक इंजन के बीच जटिलता के कई स्तर हैं। तो फिर से: आप किसके बारे में पूछ रहे हैं?
निकोल बोलस

जवाबों:


6

मुझे लगता है कि ओ ओ ओ पी एल आवश्यक नहीं है। यह अलग है जब आप shader, मॉडल, आदि वर्ग के बारे में बात करते हैं।

मूल रूप से आप खेल / इंजन आरंभीकरण पहले (और अन्य चीजों) करेंगे। फिर आप RAM (यदि आवश्यक हो) और बफर ऑब्जेक्ट्स के लिए बनावट, मॉडल और शेड्स लोड करेंगे और शेड्स अपलोड / संकलित करेंगे। उसके बाद, आप, आपके डेटा संरचना या श्रेणी में shader, मॉडल में shaders, मॉडल और बनावट बफ़र ऑब्जेक्ट्स की int ID होती है।

मुझे लगता है कि अधिकांश इंजनों में इंजन के घटक होते हैं और उनमें से सभी में कुछ इंटरफेस होते हैं। मेरे द्वारा देखे गए सभी इंजनों में कुछ घटक जैसे कि रेंडरर या सीनमेनेजर या दोनों शामिल हैं (खेल / इंजन की जटिलता पर निर्भर करता है)। आपके पास OpenGLRenderer वर्ग और / या DXRenderer हो सकते हैं जो Renderer इंटरफ़ेस को लागू करते हैं। फिर अगर आपके पास सीनमेनेजर और रेंडरर है तो आप निम्नलिखित कुछ काम कर सकते हैं:

  • Traverse SceneManager और रेंडरर को प्रत्येक वस्तु को रेंडर करने के लिए भेजें
  • ऊपरी दृश्य को कुछ दृश्य विधि में एन्क्रिप्ट करें
  • सीनियरमैन को रेंडरर के पास भेजें ताकि वह इसे संभाल सके

रेंडरर संभवतः ऑब्जेक्ट के ड्रॉ फ़ंक्शन को कॉल करेगा, जो प्रत्येक मेष के ड्रॉ फ़ंक्शन को कॉल करेगा जो कि से बना है और मेष बनावट ऑब्जेक्ट को बांध देगा, shader को बांध देगा, OpenGL ड्रा फ़ंक्शन को कॉल करेगा और फिर शेड्स, टेक्सचर और ऑब्जेक्ट डेटा बफर ऑब्जेक्ट्स का उपयोग नहीं करेगा।

नोट: यह सिर्फ उदाहरण है, आपको अधिक विवरण में दृश्य प्रबंधन का अध्ययन करना चाहिए और यह देखने के लिए अपने उपयोग के मामले का विश्लेषण करना चाहिए कि सबसे अच्छा कार्यान्वयन विकल्प क्या है

आप चाहते हैं जाहिर है, इस तरह के रूप इंजन के अन्य घटकों, है MemoryManager , ResourceLoader तो वे / अनलोड कुछ मॉडल / shaders / संरचनाओं के रूप में की जरूरत लोड कर सकता है जो दोनों वीडियो और रैम मेमोरी उपयोग की देखभाल हैं आदि,,। इसके लिए अवधारणाओं में मेमोरी कैशिंग, मेमोरी मैपिंग आदि शामिल हैं। प्रत्येक घटक के बारे में बहुत सारे विवरण और अवधारणाएं हैं।

अन्य गेम इंजनों के अधिक विस्तृत विवरण पर एक नज़र डालें, उनमें से बहुत सारे हैं और उनका प्रलेखन बहुत उपलब्ध है।

लेकिन हाँ, कक्षाएं जीवन को आसान बनाती हैं; आपको पूरी तरह से उनका उपयोग करना चाहिए और एनकैप्सुलेशन, इनहेरिटेंस, इंटरफेस और अधिक शांत सामान के बारे में याद रखना चाहिए।


यह वह उत्तर है जिसकी मुझे तलाश थी। हालाँकि, जब आप कहते हैं "... लोड होने वाले बनावट, मॉडल और शेड्स RAM (यदि आवश्यक हो) और बफर ऑब्जेक्ट्स, और शेडर्स को अपलोड / संकलित करें ..." मुझे मेरे मूल प्रश्न पर वापस लाता है; क्या मुझे मॉडल और शेड जैसी चीजों को एनकैप्सुलेट करने के लिए वस्तुओं का उपयोग करना चाहिए?
सुलिवन

ऑब्जेक्ट एक वर्ग का उदाहरण है, और 'आपको उन्हें पूरी तरह से उपयोग करना चाहिए'।
एडिन-एम

क्षमा करें, मेरा मतलब था 'मुझे वस्तुओं का उपयोग कैसे करना चाहिए'। मेरी गलती।
सुलिवन

खैर, यह आपके वर्ग डिजाइन पर निर्भर करता है। कुछ मूल उदाहरण सहज होगा, कुछ इस तरह: object3d (class) में meshes (वर्ग) है; प्रत्येक जाल में सामग्री (वर्ग) होती है; प्रत्येक सामग्री में बनावट (वर्ग, या सिर्फ आईडी) और शेडर (वर्ग) हो सकता है। लेकिन जैसा कि आप प्रत्येक घटक के बारे में पढ़ते हैं, आप देखेंगे कि सीनमेनेजर, रेंडरर, मेमोरी मैनजर बनाने के लिए अलग-अलग लेकिन समान दृष्टिकोण हैं (ये सभी एकल वर्ग या उनमें से कई हो सकते हैं, विरासत में मिले आदि)। इस विषय (खेल इंजन वास्तुकला) पर दर्जनों किताबें लिखी गई हैं, और विस्तार से सवाल का जवाब देने के लिए एक लिख सकता है।
एडिन-एम

मुझे लगता है कि यह सबसे अच्छा जवाब है जो मुझे मिलने वाला है। आपकी मदद के लिए धन्यवाद :)
सुलिवन

2

ओपनजीएल में पहले से ही कुछ 'ऑब्जेक्ट' अवधारणाएं हैं।

उदाहरण के लिए एक आईडी के साथ कुछ भी एक वस्तु के रूप में हो सकता है (विशेष रूप से 'ऑब्जेक्ट' नाम की चीजें भी हैं)। बफ़र, बनावट, वर्टेक्स बफर ऑब्जेक्ट्स, वर्टेक्स एरे ऑब्जेक्ट्स, फ़्रेम बफर ऑब्जेक्ट्स और इसी तरह। थोड़े से काम से आप उनके आसपास कक्षाएं लपेट सकते हैं। यदि आप अपने संदर्भ एक्सटेंशन का समर्थन नहीं करते हैं तो यह आपको पुराने पदावनत OpenGL फ़ंक्शन पर वापस जाने का एक आसान तरीका देता है। उदाहरण के लिए एक VertexBufferObject glBegin (), glVertex3f (), और इसी तरह का उपयोग करके वापस गिर सकता है।

ऐसे कुछ तरीके हैं जिनसे आपको पारंपरिक ओपनगेल अवधारणाओं से दूर जाने की आवश्यकता हो सकती है, उदाहरण के लिए आप बफर ऑब्जेक्ट्स में बफ़र्स के बारे में मेटाडेटा स्टोर करना चाहते हैं। उदाहरण के लिए यदि बफर वर्टिकल स्टोर करता है। शीर्ष रेखाओं का प्रारूप क्या है (जैसे स्थिति, मानदंड, टेक्सकोर्ड और इतने पर)। यह किस प्राइमिटिव का उपयोग करता है (GL_TRIANGLES, GL_TRIANGLESTRIP, आदि ...), आकार की जानकारी (कितनी झांकियां संग्रहीत की जाती हैं, कितने त्रिकोण वे प्रतिनिधित्व करते हैं, आदि ...)। बस उन्हें ड्रॉ एरेज़ कमांड में प्लग करना आसान है।

मैं आपको OGLplus को देखने की सलाह देता हूं । यह ओपन ++ के लिए C ++ बाइंडिंग है।

इसके अलावा glxx , यह केवल एक्सटेंशन लोडिंग के लिए है।

ओपनजीएल एपीआई को लपेटने के अलावा, आपको इसके शीर्ष पर थोड़ा उच्च स्तर का निर्माण करना चाहिए।

उदाहरण के लिए एक सामग्री प्रबंधक वर्ग जो आपके सभी शेड के लिए जिम्मेदार है, उन्हें लोड करना और उनका उपयोग करना। इसके अलावा यह उनके लिए संपत्तियों को स्थानांतरित करने के लिए जिम्मेदार होगा। इस तरह आप बस कॉल कर सकते हैं: material.usePhong (); material.setTexture (sometexture); material.setColor ()। यह आपको अधिक लचीलेपन की अनुमति देता है, क्योंकि आप साझा किए गए समान बफर ऑब्जेक्ट्स जैसी नई चीजों का उपयोग कर सकते हैं, जिसमें 1 बड़ा बफर है, जिसमें सभी गुण आपके ब्लॉक में 1 शेड्स का उपयोग करते हैं, लेकिन यदि यह आपको प्रत्येक shader प्रोग्राम में अपलोड करने में गिरावट का समर्थन नहीं करता है। आपके पास 1 बड़ा अखंड छायादार हो सकता है और अगर यह समर्थित है या समान छोटे शेड्स के एक गुच्छा का उपयोग करने के लिए वापस गिर सकता है तो समान रूटीन का उपयोग करके विभिन्न शेडर मॉडल के बीच स्वैप करें।

आप अपने shader कोड को लिखने के लिए GLSL के स्पेक्स से भी एक्सपेंड कर सकते हैं। उदाहरण के लिए #include आपके shader लोडिंग कोड में लागू करने के लिए अविश्वसनीय रूप से उपयोगी और बहुत आसान होगा (इसके लिए ARB एक्सटेंशन भी है)। एक्सटेंशन क्या समर्थित हैं, इसके आधार पर आप अपने कोड को मक्खी पर भी उत्पन्न कर सकते हैं, उदाहरण के लिए एक साझा समान वस्तु का उपयोग करें या सामान्य वर्दी का उपयोग करने के लिए वापस जाएं।

अंत में आप एक उच्च स्तरीय रेंडरिंग पाइपलाइन एपीआई चाहते हैं जो दृश्य रेखांकन, विशेष प्रभाव (धुंधला, चमक) जैसी चीजों को करता है, जिन चीजों के लिए कई रेंडरिंग की आवश्यकता होती है जैसे छाया, प्रकाश व्यवस्था और ऐसे। और फिर उसके ऊपर एक गेम एपीआई जिसका ग्राफिक्स एपीआई से कोई लेना-देना नहीं है, लेकिन सिर्फ एक दुनिया में वस्तुओं से संबंधित है।


2
"मैं आपको OGLplus को देखने की सलाह देता हूं। यह OpenGL के लिए C ++ बाइंडिंग है।" मैं उसके खिलाफ सिफारिश करूंगा । मैं RAII से प्यार करता हूं, लेकिन यह ज्यादातर OpenGL ऑब्जेक्ट के लिए पूरी तरह से अनुपयुक्त है। OpenGL ऑब्जेक्ट एक वैश्विक निर्माण से जुड़े हैं: OpenGL संदर्भ। इसलिए आप इन C ++ ऑब्जेक्ट्स को तब तक बनाने में असमर्थ होंगे जब तक आपके पास एक संदर्भ नहीं होगा, और यदि आप पहले से ही संदर्भ नष्ट हो गए हैं, तो आप इन ऑब्जेक्ट्स को हटाने में असमर्थ होंगे। साथ ही, यह भ्रम देता है कि आप वैश्विक स्थिति को बदले बिना वस्तुओं को संशोधित कर सकते हैं। यह एक झूठ है (जब तक आप EXT_DSA का उपयोग नहीं कर रहे हैं)।
निकोल बोलस

@ निकोलबोलस: क्या मैं यह देखने के लिए जाँच नहीं कर सकता कि क्या कोई संदर्भ है और केवल तब ही इनिशियलाइज़ करें? या शायद केवल प्रबंधकों को उन वस्तुओं को बनाने की अनुमति देता है जिनके लिए ओपनजीएल संदर्भ की आवश्यकता होती है? --- btw, ट्यूटोरियल के महान सेट (अपनी प्रोफ़ाइल में लिंक)! OpenGL / Graphics की खोज करते समय किसी तरह मैं उनके सामने कभी नहीं आया।
समौरा

@ ससुरासा: किस अंत के लिए? यदि आपके पास OpenGL ऑब्जेक्ट के लिए प्रबंधक है, तो ... आपको वास्तव में ऑब्जेक्ट्स को स्वयं का ध्यान रखने की आवश्यकता नहीं है; प्रबंधक उनके लिए यह कर सकता है। और यदि आप केवल एक संदर्भ मौजूद होने पर उन्हें इनिशियलाइज़ करते हैं, तो क्या होगा यदि आप किसी ऐसी वस्तु का उपयोग करने की कोशिश करें जो ठीक से इनिशियलाइज़ नहीं हुई थी? यह सिर्फ आपके कोडबेस में धोखाधड़ी पैदा करता है। और न ही यह कुछ भी बदलता है जो मैंने वैश्विक राज्य को छूने के बिना इन वस्तुओं को संशोधित करने की क्षमता के बारे में कहा था।
निकोल बोलस

@ एनकोलबोल: "आप इन सी ++ वस्तुओं को बनाने में असमर्थ होंगे जब तक कि आपके पास एक संदर्भ नहीं था" ... यह है कि नंगे ओपनजीएल निर्माणों का उपयोग करने की तुलना में कोई अलग है? मेरी नजर में, oglplus::Contextवर्ग इस निर्भरता को अत्यधिक दृश्यमान बनाता है - क्या यह समस्या होगी? मेरा मानना ​​है कि यह नए OpenGL उपयोगकर्ताओं को बहुत सारी समस्याओं से बचने में मदद करेगा।
xtofl

1

आधुनिक ओपन में आप लगभग पूरी तरह से अलग वस्तु और shader कार्यक्रमों का उपयोग करते हुए एक दूसरे से वस्तु प्रदान कर सकते हैं। और यहां तक ​​कि एक वस्तु के कार्यान्वयन को कई अमूर्त परतों में अलग किया जा सकता है।

उदाहरण के लिए, यदि आप एक इलाके को लागू करना चाहते हैं, तो आप एक TerrainMesh को परिभाषित कर सकते हैं जिसका निर्माता इलाके के लिए कोने और इंडेक्स बनाता है, और उन्हें सरणीबफ़र में सेट करता है, और - यदि आप इसे एक विशेषता स्थिति देते हैं - तो यह आपके डेटा को हिला देता है। यह भी पता होना चाहिए कि इसे कैसे रेंडर करना है, और रेंडरिंग को सेटअप करने के लिए किए गए सभी संदर्भ परिवर्तनों को वापस करने का ध्यान रखना चाहिए। इस वर्ग को स्वयं उस shader कार्यक्रम के बारे में कुछ भी नहीं पता होना चाहिए जो उसे रेंडर करने जा रहा है, और न ही उसे दृश्य में किसी अन्य ऑब्जेक्ट के बारे में कुछ भी पता होना चाहिए। इस वर्ग के ऊपर आप एक टेरेन को परिभाषित कर सकते हैं, जो कि shader कोड के बारे में जानता है, और इसका काम shader और TerrainMesh के बीच संबंध बनाना है। इसका मतलब यह होना चाहिए कि बनावट और समान स्थिति और बनावट में लोडिंग, और इस तरह की चीजें। इस वर्ग को कुछ भी पता नहीं होना चाहिए कि इलाके को कैसे लागू किया जाता है, एलओडी एल्गोरिथम का क्या उपयोग करता है, यह सिर्फ इलाके को चमकाने के लिए जिम्मेदार है। इसके ऊपर, आप गैर-ओएनजीएल कार्यक्षमता को परिभाषित कर सकते हैं जैसे कि बीहवॉर और टकराव का पता लगाने और ऐसे।

इस बिंदु पर आकर, भले ही ओपनजीएल को निम्न-स्तर का उपयोग करने के लिए डिज़ाइन किया गया हो, फिर भी आप एब्सट्रैक्शन की स्वतंत्र परतों का निर्माण कर सकते हैं, जो आपको एक अवास्तविक खेल के आकार के साथ कई स्तरों तक स्केल करते हैं। लेकिन आप जो परतें चाहते / चाहते हैं उनकी संख्या वास्तव में आपके इच्छित एप्लिकेशन के आकार पर निर्भर करती है।

लेकिन इस आकार के बारे में अपने आप से झूठ मत बोलो, 10k लाइन एप्लिकेशन में एकता के ऑब्जेक्ट मॉडल की नकल करने की कोशिश मत करो, परिणाम एक पूर्ण आपदा होगा। परतों का निर्माण धीरे-धीरे करें, केवल अमूर्त परतों की संख्या में वृद्धि करें, जब यह आवश्यक हो।


0

ioDoom3 शायद एक बेहतरीन शुरुआती बिंदु है, क्योंकि आप बड़ी कोडिंग प्रथा का पालन करने के लिए कारमैक पर भरोसा कर सकते हैं। इसके अलावा, मेरा मानना ​​है कि वह Doom3 में मेगाटेक्स्टुरिंग का उपयोग नहीं करता है, इसलिए यह रेंडर पाइप के रूप में अपेक्षाकृत सीधे आगे है।


6
"जैसा कि आप महान कोडिंग अभ्यास का पालन करने के लिए कार्मैक पर भरोसा कर सकते हैं" ओह यार, यह एक अच्छा है। कार्मैक महान C ++ कोडिंग अभ्यास का अनुसरण करता है। यह एक दंगा है! ओह ... तुम मजाक नहीं कर रहे थे। उम ... क्या आपने कभी उसके कोड को देखा है ? वह एक सी प्रोग्रामर है और यही वह सोचता है। जो C के लिए ठीक है, लेकिन सवाल C ++ के बारे में है
निकोल बोलस

मैं सी बैकग्राउंड से आता हूं इसलिए उसका कोड मेरे लिए बहुत मायने रखता है: पी और हां, भूकंप आधारित खेलों पर काम करने में थोड़ा समय बिताया।
च्रिस्वार्न्ज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.