क्या भैंसों को निर्वस्त्र करना चाहिए?


12

मैं OpenGL ES 2 के साथ कुछ परीक्षण कर रहा हूं और कुछ प्रश्न मिले हैं, मेरा वर्तमान कार्यक्रम इस प्रकार है:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

समस्या

दिए गए कोड क्रैश, कुछ शोधों के बाद, मुझे समझ में आया है कि: मुझे अपने इंडेक्स बफर को इनिट पार्ट ("इंडेक्स बफर ग्लबफ़रडेटा भरने के बाद") या पहले "बिंद वीएओ" से पहले इसे अनबाइंड करने की आवश्यकता है।

मेरे प्रश्न हैं:

  • क्या मैं अपने सूचकांक बफर को VAO (VAO स्टॉक इंडेक्स बफर?) में डाल सकता हूं?
  • क्या मुझे प्रत्येक अपडेट (glBufferData) के बाद बफ़र्स को खोलना था?

मेरे आवेदन में मुझे कुछ बफ़र्स मिले हैं जो प्रत्येक फ्रेम पर अपडेट किए गए हैं (एक्ज़म्पल: पार्टिकल्स) इसलिए मुझे एक ओपनगेल स्टैक मिला है जैसे:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

पहली 3 लाइनें वर्टेक्स बफर को अपडेट करती हैं, दो अंतिम ड्रा ऑब्जेक्ट, जो कुछ इस तरह होना चाहिए:

-> bind buffer 1
-> update buffer 1
-> draw

धन्यवाद

जवाबों:


12

आप अनावश्यक बंधन / बंधन पर बहुत कुछ कर रहे हैं। यदि आप एक वीएओ का उपयोग कर रहे हैं, तो आपको केवल वीएओ को बांधना चाहिए जब आप इसे सेट करते हैं और जब ज्यामिति खींचते हैं। आपको केवल VBO / IBO को फिर से बाँधना होगा जब आपको उन्हें अपडेट करने की आवश्यकता होगी।

बफर को खींचने या अपडेट करने के बाद, आपको जरूरी नहीं कि इसे खोलना है, हालांकि ऐसा करने का एक अच्छा विचार हो सकता है कि बफ़र्स को आकस्मिक लेखन से बचने के लिए बाध्य किया गया था।

अब आपके ऑपरेशन का मुट्ठी अनुक्रम लेते हुए, यह समग्र क्रम है जिसे मैं देखने की उम्मीद करूंगा:

Init पर:

  1. एक VAO बनाएँ और बाँधें। किसी भी VBO और IBO जिसे आप अनुक्रम में बांधते हैं, वर्तमान VAO (यह एक) के साथ जुड़ा होगा।

  2. इंडेक्स बफर बनाएँ और बाँधें।

    • के साथ सूचकांक बफर भरें glBufferData/glMapBuffer
  3. वर्टेक्स बफर बनाएँ और बांधें।

    • वर्टेक्स बफर भरें glBufferData/glMapBuffer
  4. glEnableVertexAttribArray/glVertexAttribPointerआदि के साथ शीर्ष गुण सेट करें ।

  5. वैकल्पिक रूप से बफ़र्स और VAO के आकस्मिक संशोधन से बचने के लिए सब कुछ unbind। पहले VAO को याद करना याद रखें । उदाहरण के लिए:glBindVertexArray(0);

ड्रा पर:

  1. यदि केवल बफ़र्स ड्राइंग :

    • VAO बाँध;
    • ड्रा कॉल करें।
  2. अगर अद्यतन और आरेखण :

    • VAO, VBO, IBO;
    • बफ़र्स को अपडेट करें (वर्टेक्स एट्रिब्यूट्स को अपडेट करना केवल तभी आवश्यक है जब वर्टेक्स प्रारूप बदल गया है);
    • ड्रा कॉल करें।
  3. बफ़र्स और VAO के आकस्मिक संशोधन से बचने के लिए वैकल्पिक रूप से unbind।

वह उतना ही सरल है। संचालन का यह क्रम समस्याओं के बिना कार्य करना चाहिए।


2
मैं अपने प्रयोगों (2014) में वास्तविक जीवन के मामलों के साथ (लेकिन GPU पर अड़चन के रूप में सरल नहीं) के साथ जोड़ना चाहूंगा, मुझे उचित आदेश देने के बाद VAO का उपयोग करने में प्रदर्शन में सुधार नगण्य (<2% सीपीयू बचत) पाया गया। रेंडर कॉल को पूरी तरह से वीबीओ सेटअप को छोड़ने के लिए लागू किया गया था जब एक ही वीबीओ पर लगातार रेंडर कॉल (10 से 33% सीपीयू बचत) का उपयोग किया गया था, और मैंने कुछ ड्राइवरों को वीएओ के साथ मारा, इसलिए मैंने उन्हें डिफ़ॉल्ट रूप से बंद कर दिया। कॉम्प्लेक्स शेड्स, MSAA, आदि का उपयोग करते समय यह और भी कम महत्वपूर्ण था, जो कि सीपीयू में अड़चन होती है, जिससे सीपीयू को मोबाइल पर भी इंतजार करना पड़ता है।
स्टीफन होकेनहुल

2
ध्यान दें कि गलत तरीके से वर्टेक्स डेटा को हार्डवेयर द्वारा समर्थित नहीं किया गया है, GPU ड्राइवरों को प्रत्येक सेटअप पर VBO डेटा को फिर से चालू करने के लिए मजबूर करेगा, जबकि ड्राइवर इसे VAO के साथ एक बार फिर से व्यवस्थित कर सकते हैं जब तक कि कुछ भी नहीं बदला जाए तो YMMV। वैसे भी संरेखित और पैड शीर्ष डेटा के लिए सबसे अच्छा है।
स्टीफन होकेनहुल

1
VAO को बाकी सब चीजों से पहले क्यों नहीं हटाया जाना चाहिए?
डैनियल सफारी

@DanielSafari, आप सेटअप के बाद मतलब है? यदि आप पहले एक बफर (बंधन बफर 0 / null) को खोलते हैं, तो यह मौजूदा VAO में बाध्यकारी बिंदु को साफ कर देगा। इसीलिए null VAO को पहले सेट करना चाहिए।
ग्लैम्पर्ट

@glampert - नहीं, यह नहीं है कि बाइंडिंग कैसे काम करती है; glVertexAttribPointer को कॉल करने पर बफर बाइंडिंग का उपयोग किया जाता है, और अन्यथा नहीं (अपवाद: GL_ELEMENT_ARRAY_BUFFER)। अपने glVertexAttribPointer कॉल के बाद बफर बाइंडिंग को बदलने से कोई प्रभाव नहीं पड़ता है।
मैक्सिमस मिनिमस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.