इंजन रेंडरिंग पाइपलाइन: शेड्स को सामान्य बनाना


10

मैं OpenGL ES 2.0 (अभी के लिए iOS) का उपयोग करके 2D गेम इंजन बनाने की कोशिश कर रहा हूं। मैंने ऑब्जेक्टिव C में एप्लिकेशन लेयर लिखी है और C ++ में एक अलग सेल्फ रेंडररजीएलईएस २० सम्‍मिलित है। रेंडर के बाहर कोई जीएल विशिष्ट कॉल नहीं किया जाता है। यह पूरी तरह से काम कर रहा है।

लेकिन मेरे पास शेड्स का उपयोग करते समय कुछ डिज़ाइन मुद्दे हैं। प्रत्येक शेडर की अपनी विशिष्ट विशेषताएँ और वर्दियाँ होती हैं जिन्हें मुख्य ड्रॉ कॉल (इस मामले में glDrawArays) से ठीक पहले सेट करने की आवश्यकता होती है। उदाहरण के लिए, कुछ ज्यामिति खींचने के लिए मैं करूँगा:

void RendererGLES20::render(Model * model)
{
    // Set a bunch of uniforms
    glUniformMatrix4fv(.......);
    // Enable specific attributes, can be many
    glEnableVertexAttribArray(......);
    // Set a bunch of vertex attribute pointers:
    glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, m->pCoords);

    // Now actually Draw the geometry
    glDrawArrays(GL_TRIANGLES, 0, m->vertexCount);

    // After drawing, disable any vertex attributes:
    glDisableVertexAttribArray(.......);
}

जैसा कि आप देख सकते हैं कि यह कोड बेहद कठोर है। अगर मुझे एक और shader का उपयोग करना है, तो रिपल इफेक्ट का कहना है, मुझे अतिरिक्त यूनीफॉर्म, वर्टेक्स एट्रीब आदि पास करने की जरूरत होगी। दूसरे शब्दों में मुझे नए जेंडर को शामिल करने के लिए RendererGLES20 रेंडर सोर्स कोड को बदलना होगा।

क्या शेडर ऑब्जेक्ट को पूरी तरह से सामान्य बनाने का कोई तरीका है? जैसे कि क्या होगा अगर मैं सिर्फ shader ऑब्जेक्ट को बदलना चाहता हूं और गेम सोर्स री-कंपाइलिंग के बारे में चिंता नहीं करता? वर्दी और विशेषताओं आदि के रेंडरर अज्ञेय को बनाने का कोई तरीका? भले ही हमें वर्दी को डेटा पास करने की आवश्यकता है, लेकिन ऐसा करने के लिए सबसे अच्छी जगह क्या है? मॉडल वर्ग? क्या मॉडल वर्ग को शेडर विशिष्ट वर्दी और विशेषताओं के बारे में पता है?

निम्नलिखित शो अभिनेता वर्ग:

class Actor : public ISceneNode
{
    ModelController * model;
    AIController * AI;
};

मॉडल नियंत्रक वर्ग: वर्ग मॉडलकंट्रोलर {वर्ग IShader * shader; int बुनावट; vec4 टिंट; फ्लोट अल्फा; संरचना वर्टेक्स * वर्टेकार्रे; };

शेडर क्लास में सिर्फ शैडर ऑब्जेक्ट, कंपाइलिंग और लिंकिंग सब-रूटिन आदि होते हैं।

गेम लॉजिक क्लास में मैं वास्तव में ऑब्जेक्ट को प्रस्तुत कर रहा हूं:

void GameLogic::update(float dt)
{
    IRenderer * renderer = g_application->GetRenderer();

    Actor * a = GetActor(id);
    renderer->render(a->model);
}

कृपया ध्यान दें कि भले ही अभिनेता ISceneNode का विस्तार करता है, मैंने अभी तक SceneGraph को लागू करना शुरू नहीं किया है। मैं इस मुद्दे को हल करते ही करूंगा।

किसी भी विचार यह कैसे सुधारें? संबंधित डिजाइन पैटर्न आदि?

सवाल पढ़ने के लिए धन्यवाद।



मुझे यकीन नहीं है कि अगर यह एक सटीक डुप्लिकेट है, लेकिन यह उस मांस के लिए मिलता है जो आप करने की कोशिश कर रहे हैं, मुझे लगता है।
सीन मिडिलिच

जवाबों:


12

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

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

ठीक है, चलो पहले शीर्ष स्वरूपों (विशेषताओं) के बारे में बात करते हैं। आप एक संरचना बनाकर एक डेटा विवरण बना सकते हैं जिसमें glVertexAttribPointerएक विशेषता के पास - सूचकांक, प्रकार, आकार आदि पास करने के लिए डेटा होता है - और पूरे वर्टेक्स प्रारूप का प्रतिनिधित्व करने के लिए उन संरचनाओं की एक सरणी होती है। इस जानकारी को देखते हुए, आप वर्चुअली विशेषताओं से संबंधित सभी जीएल राज्य को प्रोग्रामेटिक रूप से सेट कर सकते हैं।

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

इसे करने के कई तरीके हैं; उदाहरण के लिए, आपके पास shader ("attrPosition", "attrNormal", इत्यादि) में विशेषताओं के लिए नामों का एक मानक सेट हो सकता है, साथ ही कुछ कठोर-कोडित नियम जैसे "स्थिति 3 फ़्लोट्स" है। फिर आप glGetAttribLocationक्वेरी का उपयोग या उसके पास जाते हैं जो शेडर के उपयोग का गुण रखता है, और वर्टेक्स प्रारूप बनाने के लिए नियमों को लागू करता है। एक अन्य तरीका यह है कि XML स्निपेट को प्रारूप को परिभाषित करने के लिए, shader स्रोत में एक टिप्पणी में एम्बेड किया जाए और आपके टूल, या उन पंक्तियों के साथ कुछ निकाला जाए।

वर्दी के लिए, यदि आप ओपनजीएल 3.1 का उपयोग कर सकते हैं या बाद में वर्दी बफर ऑब्जेक्ट (डी 3 डी के निरंतर बफ़र्स के बराबर) का उपयोग करना एक अच्छा विचार है । काश, जीएल ES 2.0 उन नहीं है, तो वर्दी व्यक्तिगत रूप से नियंत्रित किया जाना है। ऐसा करने का एक तरीका यह होगा कि आप जिस भी पैरामीटर को सेट करना चाहते हैं, उसके लिए एक समान स्थान बनाएं, जिसमें कैमरा मैट्रिक्स, स्पेक्युलर पावर, वर्ल्ड मैट्रिक्स आदि शामिल हैं। सैम्पलर लोकेशन यहाँ भी हो सकते हैं। यह दृष्टिकोण वहाँ पर निर्भर करता है कि सभी शेड्स में साझा किए गए मापदंडों का एक मानक सेट है। प्रत्येक शेडर को हर एक पैरामीटर का उपयोग नहीं करना पड़ता है, लेकिन सभी मापदंडों को इस संरचना में होना चाहिए।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.