2012-03-26 16 views
23

मैंने ओपनजीएल और सी ++ के साथ विभिन्न डेमो परियोजनाओं पर काम किया है, लेकिन वे सभी कुछ दिलचस्प प्रभावों के साथ बस एक घन (या समान सरल जाल) प्रस्तुत करने में शामिल हैं। इस तरह के एक साधारण दृश्य के लिए, घन के लिए कशेरुक डेटा एक सुरुचिपूर्ण वैश्विक सरणी में संग्रहीत किया जा सकता है। अब मैं विभिन्न प्रकार के कई वस्तुओं के साथ, अधिक जटिल दृश्यों को प्रस्तुत करने में देख रहा हूं।ओपनजीएल और ओओपी प्रोग्राम संरचना

मैं इसे समझ में आता है वस्तुओं (Rock, Tree, Character, आदि) के विभिन्न प्रकार के विभिन्न वर्गों के लिए लगता है, लेकिन मैं कैसे सफाई से डेटा को तोड़ने के लिए सोच रहा हूँ और दृश्य में वस्तुओं के लिए कार्यक्षमता प्रतिपादन। प्रत्येक वर्ग वर्टेक्स पदों, बनावट निर्देशांक, मानक, इत्यादि की अपनी सरणी संग्रहित करेगी। हालांकि मुझे यकीन नहीं है कि ओपनजीएल कॉल कहां रखा जाए। मैं सोच रहा हूं कि मेरे पास एक लूप होगा (World या Scene कक्षा में) जो दृश्य में सभी वस्तुओं पर पुनरावृत्त करता है और उन्हें प्रस्तुत करता है।

उन्हें प्रस्तुत करना चाहिए प्रत्येक ऑब्जेक्ट (Rock::render(), Tree::render(),...) में एक रेंडर विधि को कॉल करना या एक रेंडर विधि जो पैरामीटर (render(Rock), render(Tree),...) पैरामीटर के रूप में लेती है? उत्तरार्द्ध क्लीनर लगता है, क्योंकि मेरे पास प्रत्येक वर्ग में डुप्लिकेट कोड नहीं होगा (हालांकि इसे RenderableObject वर्ग से विरासत में कम करके कम किया जा सकता है), और अगर मैं बाद में बंदरगाह करना चाहता हूं तो यह रेंडर() विधि को आसानी से बदला जा सकता है DirectX। दूसरी तरफ, मुझे यकीन नहीं है कि मैं उन्हें अलग रख सकता हूं, क्योंकि मुझे ऑब्जेक्ट्स में संग्रहीत ओपनजीएल विशिष्ट प्रकारों की आवश्यकता हो सकती है (उदाहरण के लिए वर्टेक्स बफर)। इसके अलावा, यह ऑब्जेक्ट से रेंडर कार्यक्षमता को अलग करने के लिए थोड़ा बोझिल लगता है, क्योंकि इसे ऑब्जेक्ट्स से डेटा प्राप्त करने के लिए Get() विधियों को कॉल करना होगा। अंत में, मुझे यकीन नहीं है कि यह प्रणाली उन वस्तुओं को कैसे संभालेगी जिन्हें विभिन्न तरीकों से खींचा जाना है (विभिन्न शेडर्स, शेडर्स में पास करने के लिए अलग-अलग चर)।

क्या इनमें से एक डिजाइन दूसरे की तुलना में स्पष्ट रूप से बेहतर है? मेरे कोड को व्यवस्थित और कुशल रखने के लिए मैं उन तरीकों से किस प्रकार सुधार कर सकता हूं?

उत्तर

22

सबसे पहले, प्लेटफॉर्म आजादी के साथ भी परेशान न करें। तब तक प्रतीक्षा करें जब तक आपके पास अपने आर्किटेक्चर का बेहतर विचार न हो।

बहुत सारे ड्रा कॉल/राज्य परिवर्तन करना धीमा है। जिस तरह से आप इसे इंजन में करते हैं, वह आम तौर पर एक प्रस्तुत करने योग्य वर्ग चाहते हैं जो स्वयं को आकर्षित कर सके। यह प्रस्तुत करने योग्य जो भी बफर की आवश्यकता है (उदा। वर्टेक्स बफर) और अन्य जानकारी (जैसे वर्टेक्स प्रारूप, टोपोलॉजी, इंडेक्स बफर इत्यादि) से जुड़ा होगा। शेडर इनपुट लेआउट वर्टेक्स प्रारूपों से जुड़ा जा सकता है।

आप कुछ आदिम भौगोलिक कक्षाएं चाहते हैं, लेकिन कुछ प्रकार के जाल वर्ग को जटिल बनाते हैं जो अनुक्रमित ट्राइस को संभालते हैं। एक सक्षम ऐप के लिए, आप अनियंत्रित राज्य परिवर्तन और पाइपलाइन फ्लश को कम करने के लिए अपनी छायांकन पाइपलाइन में समान इनपुट प्रकारों के लिए कॉल (और संभावित रूप से डेटा) बैच करना चाहेंगे।

शेडर्स पैरामीटर और बनावट आम तौर पर प्रस्तुत करने योग्य से जुड़े कुछ भौतिक वर्ग के माध्यम से नियंत्रित होते हैं।

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

अधिकांश इंटरैक्टिव 3 डी ऐप्स का स्क्रिप्टिंग/व्यवहार हिस्सा कसकर जुड़ा हुआ है या इसके दृश्य ग्राफ नोड फ्रेमवर्क और एक ईवेंट/मैसेजिंग सिस्टम में लगा हुआ है।

यह सब एक उच्च स्तरीय पाश में एक साथ फिट बैठता है जहां आप समय के आधार पर प्रत्येक उपप्रणाली को अद्यतन करते हैं और वर्तमान फ्रेम पर दृश्य खींचते हैं।

जाहिर है कि बहुत सारे विवरण बाकी हैं लेकिन यह सामान्य और निष्पादक के रूप में आप किस प्रकार की दृश्य जटिलता के लक्ष्य बन रहे हैं, इस पर निर्भर करता है कि यह बहुत जटिल हो सकता है।

draw(renderable) का आपका प्रश्न, बनाम renderable.draw() अधिक या कम अप्रासंगिक है जब तक आप यह निर्धारित नहीं करते कि सभी भागों एक साथ कैसे फिट होते हैं।

[अपडेट]इस अंतरिक्ष में थोड़ा और अधिक में काम करने के बाद, कुछ जोड़ा अंतर्दृष्टि:

कहा करने के बाद वाणिज्यिक इंजन में, आमतौर पर अधिक draw(renderBatch) की तरह है जहां प्रत्येक प्रस्तुत करना इसके कि, बैच वस्तुओं की एक एकत्रीकरण है जो जीपीयू के कुछ सार्थक तरीके से समरूप होते हैं, क्योंकि विषम वस्तुओं (एक "शुद्ध" ओओपी दृश्य ग्राफ में पॉलिमॉर्फिज्म के माध्यम से) और obj.draw() पर कॉल करने से एक-एक-एक में भयानक कैश इलाका होता है और आमतौर पर जीपीयू संसाधनों का अक्षम उपयोग होता है। डेटा अंतर्निहित दृष्टिकोण लेने के लिए डेटा-ओरिएंटेड दृष्टिकोण लेना बहुत उपयोगी है कि एक इंजन अपने अंतर्निहित ग्राफिक्स एपीआई को सबसे प्रभावी तरीके से कैसे वार्ता करता है, कोड संरचना/पठनीयता को नकारात्मक रूप से प्रभावित किए बिना जितना संभव हो सके चीजों को बैच करना।

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

+1

धन्यवाद, यह मुझे काम करने के लिए कुछ विचार देता है। एक बात जो मुझे समझ में नहीं आती है वह आपके द्वारा वर्णित रेंडर करने योग्य वर्ग और जाल वर्ग के बीच भेद है। क्या मैं नहीं चाहता कि जाल वर्ग एक प्रस्तुत करने योग्य हो जो खुद को आकर्षित कर सके? एक उच्च स्तर पर, मुझे लगता है कि डिजाइन की तुलना में यह डिजाइन अधिक जटिल होने जा रहा है। क्या आप किसी भी ऑनलाइन संसाधनों के बारे में जानते हैं जो एक प्रतिपादन प्रणाली को डिजाइन करने के लिए एक अच्छा परिचय प्रदान करते हैं? अधिकांश ओपनजीएल ट्यूटोरियल जिन्हें मैंने पाया है, चित्रकला, टेक्सचरिंग और कुछ त्रिकोणों को प्रकाश देने की प्रक्रिया को बिना किसी बड़े चित्र वास्तुकला की चर्चा के परिचय देते हैं। – Jeff

+0

@ जेफ: नहीं। जाल सिर्फ कशेरुक डेटा का संग्रह है। एक जाल * अकेला * पर्याप्त नहीं है। कुछ प्रस्तुत करने के लिए, आपको एक जाल, शेडर जिसे आप इसके साथ प्रस्तुत करना चाहते हैं, और अन्य मिश्रित राज्य (बनावट, आदि) की आवश्यकता है। –

+0

@ जेफ क्या निकोल ने कहा सही है। जो कुछ भी आप आकर्षित करते हैं वह एक जाल नहीं होगा (उदाहरण के लिए आप लाइनों या कुछ अन्य आदिम जैसे कि जाल की तरह जा सकते हैं जहां जाल अधिक हो सकता है)। एक जाल वर्ग को ज्यामिति (और कभी-कभी भौतिक सूचकांक प्रति त्रि, और समूह/पदानुक्रम) का वर्णन करना चाहिए, लेकिन बहुत कुछ नहीं। गेम इंजन विकास के बारे में बात करने वाली किताबों में देखें (भले ही आप कोई गेम नहीं बना रहे हों)। एक अच्छा "गेम इंजन आर्किटेक्चर" है, "गेम प्रोग्रामिंग जेम्स" और "गेम इंजन जेम्स" भी बहुत अच्छी जानकारी है। आप gamedev.net मंचों को भी छिपाना चाहते हैं –

3

मुझे लगता है कि OpenSceneGraph एक उत्तर है। इसे और उसके implementation पर एक नज़र डालें। यह आपको ओपनजीएल, सी ++ और ओओपी का उपयोग करने के तरीके पर कुछ दिलचस्प अंतर्दृष्टि प्रदान करेगा।

+0

सुझाव के लिए धन्यवाद; मैं इसे देख लूंगा और देख सकता हूं कि मैं इससे कुछ प्राप्त कर सकता हूं या नहीं। मुझे लगता है कि मुझे वास्तव में क्या चाहिए, हालांकि, स्केल में थोड़ा सा छोटा है, एक रोशनी, बनावट, कताई घन (उदाहरण के लिए) और एक पूर्ण ग्राफिक्स लाइब्रेरी को प्रस्तुत करने के विशिष्ट ओपनजीएल ट्यूटोरियल के बीच कहीं एक कदम पत्थर। – Jeff

0

यहां मैंने भौतिक सिमुलेशन के लिए लागू किया है और जो बहुत अच्छी तरह से काम करता है और अमूर्तता के अच्छे स्तर पर था। सबसे पहले मैं इस तरह के रूप वर्गों में कार्यक्षमता अलग चाहते हैं: - कंटेनर कि सभी आवश्यक वस्तु जानकारी

  • AssetManager रखती है -

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

    समस्या यह है कि GPU अब GPGPU (सामान्य प्रयोजन GPU) तो ओपन है या Vulkan न केवल एक प्रतिपादन ढांचा अब और है। उदाहरण के लिए जीपीयू पर शारीरिक गणना की जा रही है।इसलिए रेंडरर अब GPUManager और उसके ऊपर के अन्य सार तत्वों जैसे कुछ में बदल सकता है। ड्रॉ करने का सबसे इष्टतम तरीका भी एक कॉल में है। दूसरे शब्दों में, पूरे दृश्य के लिए एक बड़ा बफर जिसे अत्यधिक CPU < -> GPU संचार को रोकने के लिए गणना शेडर्स के माध्यम से भी संपादित किया जा सकता है।

  • संबंधित मुद्दे