ग्राफ़-आधारित सामग्री प्रणाली में, मैं विभिन्न प्रकार के इनपुट और आउटपुट प्रकारों का समर्थन कैसे कर सकता हूं?


11

यहाँ छवि विवरण दर्ज करें

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


पृष्ठभूमि:

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

इस प्रणाली को थोड़ा और अधिक लचीला बनाने के लिए, मैं आमतौर पर इसे इस तरह से लिखता हूं जिससे मुझे किसी भी नाम / प्रकार की वर्दी पास करने का प्रयास करने की अनुमति मिलती है [अर्थात: SetUniform_Vec4 ("AmbientColor", colorVec4); जो "colorVec4" कहा जाता है कि अगर वर्दी सामग्री में मौजूद है एक विशेष 4d वेक्टर को AmbientColor वर्दी स्थापित करेगा।]

class Material
{
    private:
       int shaderID;
       string vertShaderPath;
       string fragSahderPath;

       void loadShaderFiles(); //load shaders from files at internal paths.
       void buildMaterial(); //link, compile, buffer with OpenGL, etc.      

    public:
        void SetGenericUniform( string uniformName, int param );
        void SetGenericUniform( string uniformName, float param );
        void SetGenericUniform( string uniformName, vec4 param );
        //overrides for various types, etc...

        int GetUniform( string uniformName );
        float GetUniform( string uniformName );
        vec4 GetUniform( string uniformName );
        //etc...

        //ctor, dtor, etc., omitted for clarity..
}

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


सवाल:

यही वह जगह है जहां मैं अब तक हूं, इसलिए मैं यह अध्ययन करने की कोशिश कर रहा हूं कि अन्य रेंडरिंग इंजन अपनी सामग्री प्रणालियों को कैसे संभालते हैं।

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

मैं जो बता सकता हूं, उस तरह के सिस्टम को लागू करने से सबक्लासेस (टेक्सचरनरोड, फ्लोटनोड, लेरपीनोड, आदि) की एक किस्म के साथ एक सरल सामग्री मैटेरियल क्लास होगी। जहां प्रत्येक MaterialNode उपवर्ग में MaterialConnections होगा।

class MaterialConnection
{
    MatNode_Out * fromNode;
    MatNode_In * toNode;
}

class LerpNode : MaterialNode
{
    MatNode_In x;
    MatNode_In y;
    MatNode_In alpha;

    MatNode_Out result;
}

यह बहुत ही मूल विचार है, लेकिन मैं थोड़ा अनिश्चित हूं कि इस प्रणाली के कुछ पहलू कैसे काम करेंगे:

1.) यदि आप अवास्तविक इंजन 4 का उपयोग करने वाले विभिन्न 'मटीरियल एक्सप्रेशंस' (नोड्स) को देखते हैं, तो आप देखेंगे कि उनमें से प्रत्येक में विभिन्न प्रकार के इनपुट और आउटपुट कनेक्शन हैं। कुछ नोड्स आउटपुट फ्लोट करते हैं, कुछ आउटपुट वेक्टर 2, कुछ आउटपुट वेक्टर 4, आदि। मैं ऊपर दिए गए नोड्स और कनेक्शन को कैसे सुधार सकता हूं ताकि वे विभिन्न प्रकार के इनपुट और आउटपुट प्रकारों का समर्थन कर सकें? क्या MatNode_Out_Float और MatNode_Out_Vec4 (और इसी तरह) के साथ MatNode_Out को उप-वार करना एक बुद्धिमान विकल्प होगा?

2.) आखिरकार, इस तरह की प्रणाली जीएलएसएल शेड्स से कैसे संबंधित है? UE4 (और इसी तरह ऊपर से जुड़ी अन्य प्रणालियों के लिए) को देखते हुए, उपयोगकर्ता को अंततः कुछ सामग्री नोड को विभिन्न मापदंडों के साथ बड़े नोड में प्लग करने की आवश्यकता होती है जो शेडर मापदंडों (आधार रंग, धातु, चमक, उत्सर्जन, आदि) का प्रतिनिधित्व करते हैं। । मेरी मूल धारणा यह थी कि UE4 में कई तरह के यूनिफॉर्म के साथ किसी तरह का कठोर कोडेड 'मास्टर शेडर' था, और उपयोगकर्ता जो कुछ भी अपनी 'सामग्री' में करता है, बस 'मास्टर शेडर' को पास कर दिया जाता है, जब वे अपने नोड्स को 'प्लग' में रखते हैं। मास्टर नोड '।

हालाँकि, UE4 प्रलेखन स्थिति:

"प्रत्येक नोड में एचएलएसएल कोड का एक स्निपेट होता है, जो एक विशिष्ट कार्य करने के लिए नामित होता है। इसका मतलब है कि जैसे ही आप एक सामग्री का निर्माण करते हैं, आप दृश्य स्क्रिप्टिंग के माध्यम से एचएलएसएल कोड बना रहे हैं।"

यदि यह सच है, तो क्या यह प्रणाली एक वास्तविक shader स्क्रिप्ट उत्पन्न करती है? यह कैसे काम करता है?


1
अपने प्रश्न से संबंधित: gameangst.com/?p=441
glampert

जवाबों:


10

मैं अपने ज्ञान का सबसे अच्छा जवाब देने की कोशिश करूँगा, यूई 4 के विशिष्ट मामले के बारे में थोड़ा ज्ञान के साथ, बल्कि सामान्य तकनीक पर।

ग्राफ़ पर आधारित सामग्री उतनी ही प्रोग्रामिंग होती है जितनी कि कोड को स्वयं लिखना। यह सिर्फ कोड पर कोई पृष्ठभूमि वाले लोगों के लिए ऐसा महसूस नहीं करता है, जिससे यह प्रतीत होता है कि आसान है। इसलिए, जब एक डिजाइनर "ऐड" नोड को जोड़ता है, तो वह मूल रूप से ऐड (वैल्यू 1, वैल्यू 2) लिख रहा है और आउटपुट को कुछ और से जोड़ रहा है। यह वही है जो उनका मतलब है कि प्रत्येक नोड एचएलएसएल कोड उत्पन्न करेगा, या तो एक फ़ंक्शन कॉल या सीधे निर्देश।

अंत में, सामग्री ग्राफ का उपयोग करना पूर्वनिर्धारित कार्यों के पुस्तकालय के साथ कच्चे शेड की प्रोग्रामिंग करने जैसा है जो कुछ सामान्य उपयोगी चीजें करते हैं, और यही यूई 4 भी करता है। इसमें shader कोड की एक लाइब्रेरी है जो एक shader संकलक लागू होने पर अंतिम shader स्रोत में ले जाएगा और इंजेक्ट करेगा।

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

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

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

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

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

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

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

इसे लपेटने के लिए, मेरा सुझाव है कि प्रत्येक ग्राफ को संभालने के लिए सिर्फ एक .material फ़ाइल। विकास के दौरान, इसमें संभवतः डिबग करने के लिए एक पाठ आधारित प्रारूप होगा और फिर रिलीज के लिए बाइनरी को पैक या संकलित किया जाएगा। प्रत्येक .material N नोड्स और N कनेक्शनों से बना होता है, जो कि SQL डेटाबेस जैसा होता है। प्रत्येक नोड के पास एन फ़ील्ड होंगे, जिनके नाम और कुछ झंडे प्रकारों के लिए स्वीकार किए जाते हैं, यदि इसके इनपुट या ouput, यदि प्रकार का अनुमान लगाया जाता है, आदि। लोड की गई सामग्री को रखने के लिए रनटाइम डेटा संरचना केवल सपाट और सरल होगी, इसलिए संपादक इसे आसानी से अनुकूलित कर सकते हैं और फ़ाइल में वापस सहेज सकते हैं।

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

मुझे बताएं कि क्या आपको मेरे विवरण में अतिरिक्त विवरण या किसी फिक्सिंग की आवश्यकता है, मैंने सभी पाठों का अवलोकन खो दिया है।


मैं आपको इतना विस्तृत और उत्कृष्ट उत्तर लिखने के लिए धन्यवाद नहीं दे सकता। मुझे ऐसा लगता है कि मेरे पास एक महान विचार है कि मुझे यहां से कहां जाना चाहिए! धन्यवाद!
MrKatSwordfish

1
कोई समस्या नहीं दोस्त, अगर आपको और मदद की ज़रूरत हो तो मुझे बेझिझक मैसेज करें। मैं वास्तव में अपने स्वयं के साधनों के लिए कुछ समकक्ष काम कर रहा हूं, इसलिए यदि आप विचारों का व्यापार करना चाहते हैं, तो मेरे अतिथि बनें! एक अच्छी दोपहर है: D
Grimshaw
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.