गेम इंजन डिज़ाइन - Ubershader - शेडर प्रबंधन डिज़ाइन [बंद]


18

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

मेरा सवाल यह है कि मुझे संसाधनों, उदाहरणों, लेखों के बारे में कहां मिलें कि कैसे एक shader प्रबंधन प्रणाली को प्रभावी ढंग से लागू किया जाए? क्या किसी को पता है कि बड़े खेल इंजन ऐसा कैसे करते हैं?


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

दुर्भाग्य से, हम अब "संसाधन अनुरोध" प्रश्नों को स्वीकार नहीं करते हैं।
4

जवाबों:


23

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

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

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

यह एक ubershader दृष्टिकोण के समान नहीं है। Ubershaders वे हैं जहाँ आपने shader के एक सेट में हर चीज के लिए आवश्यक सभी कोड डाल दिए हैं, शायद #ifdefs और वर्दी का उपयोग कर रहे हैं और उन्हें संकलित या चलाते समय सुविधाओं को चालू और बंद करना पसंद करते हैं। मैं व्यक्तिगत रूप से ubershader दृष्टिकोण को घृणा करता हूं, लेकिन कुछ बल्कि प्रभावशाली एएए इंजन उनका उपयोग करते हैं (विशेष रूप से क्रायटेक ध्यान में आता है)।

आप कई तरीकों से shader chunks को संभाल सकते हैं। सबसे उन्नत तरीका - और यदि आप GLSL, HLSL, और कन्सोल का समर्थन करने की योजना बनाते हैं - तो एक shader भाषा के लिए एक parser लिखना है (शायद HLSL / Cg या GLSL के करीब जितना आप अपने देवताओं के लिए अधिकतम "समझ" के लिए कर सकते हैं) ) जो तब स्रोत से स्रोत अनुवाद के लिए इस्तेमाल किया जा सकता है। एक अन्य तरीका यह है कि XML फ़ाइलों या जैसे जैसे, shader chunks को लपेटा जाए

<shader name="example" type="pixel">
  <input name="color" type="float4" source="vertex" />
  <output name="color" type="float4" target="output" index="0" />
  <glsl><![CDATA[
     output.color = vec4(input.color.r, 0, 0, 1);
  ]]></glsl>
</shader>

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

एक्सएमएल नमूना तब कुछ इसी तरह उत्पन्न हो सकता है (माफी अगर यह अमान्य GLSL है, तो मुझे उस एपीआई के अधीन होने में थोड़ी देर हो गई है):

layout (location=0) in vec4 input_color;
layout (location=0) out vec4 output_color;

struct Input {
  vec4 color;
};
struct Output {
  vec4 color;
}

void main() {
  Input input;
  input.color = input_color;
  Output output;

  // Source: example.shader
#line 5
  output.color = vec4(input.color.r, 0, 0, 1);

  output_color = output.color;
}

आप थोड़े होशियार हो सकते हैं और अधिक "कुशल" कोड उत्पन्न कर सकते हैं, लेकिन ईमानदारी से कोई भी छाया संकलक जो कुल बकवास नहीं है, आपके लिए उस उत्पन्न कोड से अतिरेक को दूर करने वाला है। हो सकता है कि नए GLSL आपको फ़ाइल का नाम #lineअभी भी कमांड्स में रखने दें, लेकिन मुझे पता है कि पुराने संस्करण बहुत कम हैं और इसका समर्थन नहीं करते हैं।

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

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

Ubershader दृष्टिकोण का अर्थ है कुछ सुविधाओं के लिए "अच्छी तरह से ज्ञात" पूर्वप्रक्रमक निर्देशों को परिभाषित करना और फिर अलग-अलग कॉन्फ़िगरेशन के साथ अलग-अलग सामग्रियों के लिए पुन: जमा करना। उदाहरण के लिए, एक सामान्य मानचित्र के साथ किसी भी सामग्री के लिए जिसे आप परिभाषित कर सकते हैं USE_NORMAL_MAPPING=1और फिर अपने पिक्सेल-स्टेज ubershader में बस:

#if USE_NORMAL_MAPPING
  vec4 normal;
  // all your normal mapping code
#else
  vec4 normal = normalize(in_normal);
#endif

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

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

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