XNA का स्प्राइटबैच वास्तव में कैसे काम करता है?


38

अधिक सटीक होने के लिए, अगर मुझे एक और एपीआई (उदाहरण के लिए ओपनजीएल) में खरोंच से इस कार्यक्षमता को फिर से बनाने की आवश्यकता है, तो क्या करने में सक्षम होने की आवश्यकता होगी?

मेरे पास कुछ चरणों का एक सामान्य विचार है, जैसे कि यह ऑर्थोग्राफ़िक प्रोजेक्शन मैट्रिक्स कैसे तैयार करता है और प्रत्येक ड्रॉ कॉल के लिए एक क्वाड बनाता है।

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

यदि संभव हो तो मैं आभारी रहूंगा यदि आप मुझे उस प्रक्रिया से मार्गदर्शन कर सकते हैं जब SpriteBatch.Begin () को SpriteBatch.End () तक कहा जाता है, तो कम से कम डिफ़ॉल्ट डिफर्ड मोड का उपयोग करते समय।


OpenGL के माध्यम से मोनोमेग में इसे कैसे लागू किया गया है, इस पर एक नज़र डालें: github.com/mono/MonoGame/blob/master/MonoGame.Framework/…
Den

क्या आपने Microsoft.Xna.Graphics पर DotPeek या Reflector का उपयोग करने की कोशिश की (मैं हालांकि अवैध कुछ भी करने का सुझाव नहीं दे रहा हूँ :))?
डेन

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

हाँ, यही कारण है कि मैंने एक टिप्पणी का उपयोग किया है। मुझे लगता है कि एंड्रयू रसेल इस सवाल का जवाब देने के लिए एक अच्छे व्यक्ति हो सकते हैं। वह इस समुदाय में सक्रिय है और ExEn पर काम कर रहा है, जो MonoGame: andrewrussell.net/exen का विकल्प है ।
डेन

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

जवाबों:


42

मैं एक क्रॉस-प्लेटफ़ॉर्म इंजन पर काम कर रहा हूँ, जिसके लिए मैंने डिफ्रेस्ड मोड में स्प्राइटबच के व्यवहार को दोहराया है, इसलिए यहाँ पर मेरे द्वारा अब तक रिवर्स किए गए कदम हैं:

  1. SpriteBatch निर्माता: एक बनाता है DynamicIndexBuffer, DynamicVertexBufferऔर की सरणी VertexPositionColorTextureतय आकार की (इस मामले में, अधिकतम बैच आकार - स्प्राइट के लिए 2048 और 8192 कोने के लिए)।

    • इंडेक्स बफर क्वैड्स के वर्टेक्स इंडेक्स से भरा होता है जो (0-1-2, 0-2-3, 4-5-6, 4-6-7 और इसी तरह) निकाला जाएगा।
    • SpriteInfoसंरचनाओं का एक आंतरिक सरणी भी बनाया गया है। यह टेम्पोरल स्प्राइट सेटिंग्स को स्टोर करेगा जब इसका उपयोग बैचिंग के लिए किया जाएगा।
  2. SpriteBatch.Begin: आंतरिक रूप से मान संग्रहीत कर लेता BlendState, SamplerStateनिर्दिष्ट, आदि और चेक अगर यह एक के बिना दो बार बुलाया गया है SpriteBatch.Endके बीच में।

  3. SpriteBatch.Draw: सभी स्प्राइट जानकारी (बनावट, स्थिति, रंग) लेता है और इसे एक में कॉपी करता है SpriteInfo। यदि अधिकतम बैच आकार तक पहुँच जाता है, तो पूरे बैच को नए स्प्राइट्स के लिए जगह बनाने के लिए तैयार किया जाता है।

    • SpriteBatch.DrawStringबस Drawस्ट्रिंग और रिक्ति को ध्यान में रखते हुए, स्ट्रिंग के प्रत्येक चरित्र के लिए जारी करता है।
  4. SpriteBatch.End: निम्नलिखित कार्य करता है:

    • में निर्दिष्ट रेंडर राज्यों को सेट करता है Begin
    • ऑर्थोग्राफ़िक प्रोजेक्शन मैट्रिक्स बनाता है।
    • SpriteBatchShader को लागू करता है ।
    • बांधता है DynamicVertexBufferऔर DynamicIndexBuffer
    • निम्न बैचिंग ऑपरेशन करता है:

      startingOffset = 0;
      currentTexture, oldTexture = null;
      
      // Iterate through all sprites
      foreach SpriteInfo in SpriteBuffer
      {
          // Store sprite index and texture
          spriteIndex = SpriteBuffer.IndexOf(SpriteInfo);
          currentTexture = SpriteInfo.Texture;
      
          // Issue draw call if batch count > 0 and there is a texture change
          if (currentTexture != oldTexture)
          {
              if (spriteIndex > startingOffset)
              {
                  RenderBatch(currentTexture, SpriteBuffer, startingOffset,
                              spriteIndex - startingOffset);
              }
              startingOffset = spriteIndex;
              oldTexture = currentTexture;
          }
      }
      
      // Draw remaining batch and clear the sprite data
      RenderBatch(currentTexture, SpriteBuffer, startingOffset,
                  SpriteBuffer.Count - startingOffset);
      SpriteBuffer.Clear();
  5. SpriteBatch.RenderBatch:SpriteInfo बैच में प्रत्येक के लिए निम्नलिखित कार्यों को निष्पादित करता है :

    • स्प्राइट की स्थिति लेता है और उत्पत्ति और आकार के अनुसार चार कोने की अंतिम स्थिति की गणना करता है। मौजूदा रोटेशन को लागू करता है।
    • यूवी निर्देशांक की गणना करता है और SpriteEffectsउनके लिए निर्दिष्ट लागू होता है।
    • स्प्राइट रंग की नकल करता है।
    • इन मानों को VertexPositionColorTextureपहले बनाए गए तत्वों की सरणी में संग्रहीत किया जाता है । जब सभी स्प्राइटों की गणना की गई है, SetDataपर कॉल किया जाता है DynamicVertexBufferऔर DrawIndexedPrimitivesकॉल जारी किया जाता है।
    • शीर्ष shader केवल एक tranform कार्रवाई करता है, और पिक्सेल shader बनावट से प्राप्त रंग पर टिनिंग लागू करता है।

यह वही है जो मुझे चाहिए, बहुत बहुत धन्यवाद! मुझे उस सब को अवशोषित करने के लिए थोड़ा सा लिया, लेकिन मुझे लगता है कि मुझे आखिरकार सभी विवरण मिल गए। एक जिसने मेरा ध्यान आकर्षित किया और मैं पहले से पूरी तरह से अवगत नहीं था, यहां तक ​​कि आस्थगित मोड में भी, अगर मैं किसी भी तरह से मेरा SpriteBatch.Draw Texture करके कॉल कर सकता हूं (यानी अगर मुझे इन कॉल के आदेश की परवाह नहीं है) तो यह होगा रेंडरबैच संचालन की संख्या को कम करें, और संभवतः प्रतिपादन को गति दें।
डेविड गॉविया

वैसे, मैं दस्तावेज़ीकरण में नहीं मिल सकता है - बफर पूर्ण होने से पहले आप ड्रॉ कॉल की सीमा क्या कर सकते हैं? और क्या कॉलट्राट उस स्ट्रिंग में वर्णों की पूरी मात्रा से उस बफर को भरता है?
डेविड गौवेया

प्रभावशाली! आपका इंजन ExEn और MonoGame की तुलना कैसे करेगा? क्या इसके लिए मोनोऑटच और मोनोऑन्ड्रोइड की भी आवश्यकता होगी? धन्यवाद।
Den

@DavidGouveia: 2048 स्प्राइट अधिकतम बैच आकार है - उत्तर को संपादित किया और इसे सुविधा के लिए जोड़ा। हां, बनावट के अनुसार छंटनी और जेड-बफर को स्प्राइट ऑर्डर करने का ध्यान रखना, न्यूनतम ड्रॉ कॉल का उपयोग करेगा। यदि आपको इसकी आवश्यकता है, तो SpriteSortMode.Textureजो भी आप चाहते SpriteBatchहैं उसे क्रमबद्ध करने के लिए लागू करने का प्रयास करें और छँटाई करने दें।
r2d2rigo

1
@ डन: एक्सन और मोनोगेम निचले स्तर के एपीआई हैं जो एक्सएनए कोड को गैर-विंडोज प्लेटफॉर्म में चलाने की अनुमति देते हैं। जिस प्रोजेक्ट पर मैं काम कर रहा हूं, वह एक घटक-आधारित इंजन है जो विशुद्ध रूप से C # में लिखा गया है, लेकिन हमें सिस्टम एपीआई तक पहुंच प्रदान करने के लिए एक बहुत पतली परत की आवश्यकता है (यह वह जगह है जहां मैं काम कर रहा हूं)। हमने SpriteBatchसुविधा के लिए पुन: लागू करने का विकल्प चुना । और हाँ, यह सभी C # के बाद से MonoTouch / MonoDroid की आवश्यकता है!
r2d2rigo

13

केवल यह बताना चाहते हैं कि XNA स्प्राइटबच कोड को DirectX में पोर्ट कर दिया गया है और XNA टीम के पिछले सदस्य द्वारा OSS के रूप में जारी किया गया है। इसलिए यदि आप यह देखना चाहते हैं कि यह XNA में कैसे काम करता है तो आप यहाँ जाएँ।


+1 के लिए "कोड मैं कभी भी उपयोग नहीं करूंगा, लेकिन स्किम पर दिलचस्प है"
काइल बरन

मूल C ++ के रूप में XNA स्प्राइटबैच का नवीनतम संस्करण GitHub h / cpp पर पाया जा सकता है । एक बोनस के रूप में, एक DirectX12 संस्करण भी उपलब्ध है h / cpp
चक वाल्बर्न
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.