ओपनजीएल: क्या वीबीओ को निर्दिष्ट किए बिना वीएओ का उपयोग करना संभव है


12

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

मुझे इस पर कोई डेमो नहीं मिला, इसलिए मैंने बस इसे आज़माने का फैसला किया। लेकिन यह काम नहीं करता है और glDrawArrayकॉल पर क्रैश हो जाता है । ऐसा लगता है कि VBO बाध्य नहीं है। यहाँ कोड का उपयोग कर रहा हूँ:

प्रतिपादन:

/* Prepare vertex attributes */
glBindVertexArrayOES(vao);

/* Upload the buffer to the GPU */
glBindBuffer(GL_ARRAY_BUFFER, pool->next());
glBufferSubData(GL_ARRAY_BUFFER, 0, parts * buffer.stride() * 6, buffer.getBuffer());

/* Draw the triangles */
glDrawArrays(GL_TRIANGLES, 0, parts * 6);

glBindVertexArrayOES(0);

VAO निर्माण:

glBindVertexArrayOES(vao);

glEnableVertexAttribArray(ls.position);
glVertexAttribPointer(ls.position, 2, GL_FLOAT, GL_FALSE, buffer.stride(), 0);

glEnableVertexAttribArray(ls.color);
glVertexAttribPointer(ls.color, 3, GL_FLOAT, GL_FALSE, buffer.stride(), GL_BUFFER_OFFSET(buffer.dataTypeSize * 2));

glBindVertexArrayOES(0);

जहां lsएक साधारण structहै जो विशेषता स्थानों को रखता है।

रेंडरिंग भाग में, स्वैपिंग glBindBufferऔर उसके glBindVertexArrayOESआसपास भी काम नहीं किया।

तो, सवाल यह है कि क्या ऐसा करना भी संभव है, या मुझे प्रत्येक बफर को एक वीएओ के लिए बनाना होगा? और अगर मुझे प्रत्येक वीबीओ के लिए एक वीएओ बनाना है, तो क्या वीएओ के glBufferSubDataसाथ संयोजन में वीबीओ के डेटा को अपडेट करना संभव है ?

जवाबों:


18

VAO में "glBindBuffer" राज्य शामिल नहीं है, इसके अपवाद के साथ GL_ELEMENT_ARRAY_BUFFERबाध्यकारी राज्य है। आप जो समझ नहीं रहे हैं, वह glBindBuffer(GL_ARRAY_BUFFER) कुछ भी नहीं करता है । खैर, यह कुछ भी नहीं करता है जहाँ तक प्रतिपादन का संबंध है। कोशिश करो; glDraw * बुलाने से पहले सही, कॉल glBindBuffer(GL_ARRAY_BUFFER, 0); आपका प्रतिपादन ठीक काम करेगा।

जिस तरह से glVertexAttribPointerकाम करता है, यह उस समय जोglVertexAttribPointer GL_ARRAY_BUFFER के लिए बाध्य है, उसे कहा जाता है । रेंडर समय पर नहीं। बाद में नहीं। ठीक उसी क्षण। यह जो भी बफर ऑब्जेक्ट था, उसे ले लेता है और इसे ओपनजीएल राज्य के एक अन्य टुकड़े में संग्रहीत करता है, जिसे VAO के भीतर समझाया जाता है।

सामान्य तौर पर, आपके पास दो विकल्प होते हैं, उनमें से एक जो नया है और संभवत: इस समय का उपयोग नहीं किया जाना चाहिए।

आपका पहला विकल्प सभी वस्तुओं को डालना है जो एक ही शीर्ष प्रारूप का उपयोग करते हैं (यानी: बफर ऑब्जेक्ट और ऑफसेट के अलावा सब कुछ) एक ही बफर ऑब्जेक्ट में। मूल रूप से, एक विशाल सरणी का निर्माण करें जिसमें सभी ऑब्जेक्ट के लिए सभी कोने हैं जो समान प्रारूप का उपयोग करते हैं।

जब रेंडर करने का समय आता है, तो आप कोने के एक हिस्से को प्रस्तुत कर सकते हैं। glDrawArraysरेंडर करने के लिए तत्वों की एक श्रृंखला लेता है, और आप अपने सूचकांकों glDrawElementsको समान करने के लिए समायोजित कर सकते हैं । वैकल्पिक रूप से, आप शीर्षकोंglDrawElementsBaseVertex को पूर्वाग्रह करने के लिए उपयोग कर सकते हैं , ताकि प्रत्येक सूचकांक में एक ऑफसेट जोड़ा जाए। यह ऑफ़सेट बड़े सरणी में उस शीर्ष से पहले कोने की संख्या है।

अन्य विकल्प जीएल 4.3 में जोड़े गए अपेक्षाकृत नए प्रारूप विशेषता पृथक्करण प्रणाली का उपयोग करना है । यह आपको प्रारूप को रीसेट किए बिना बफ़र्स को बदलने की अनुमति देगा। इस प्रकार आप एक एकल VAO को बांध देंगे, फिर बस जरूरत के अनुसार अलग-अलग बफ़र्स में स्थानापन्न कर सकते हैं glBindVertexBuffer। यह ES 3.1 में भी उपलब्ध है।


1
NV GL4.3 ड्राइवर अब पूर्ण रिलीज़ हैं।
मैक्सिमस मिनिमस

GlVertexAttribPointer के काम करने के तरीके को समझाने के लिए आपका बहुत-बहुत धन्यवाद। यह ज्ञानवर्धक था और बताता है कि यह क्यों और कैसे काम करता है।
Martijn कोर्टो

5

VAO glVertexAttribPointer स्थिति संग्रहीत करता है। VAO बदलने से वर्तमान glBindBuffer प्रभावित नहीं होता है, और न ही glBindBuffer को बदलने से VAO प्रभावित होता है। केवल glVertexAttribPointer कॉल VAO को प्रभावित करता है, कॉल पर उपयोग में बफर रिकॉर्ड करके।

तो आपके प्रश्न का उत्तर नहीं है।

एक विकल्प यदि आप वस्तुओं की संख्या को कम करना चाहते हैं, तो अपने सभी जाल डेटा को एक बड़े VBO में डालें और निर्दिष्ट करें कि 'डेटा' और 'काउंट' तर्कों का उपयोग करके glDrawArrays कॉल में मेष डेटा कहाँ रहता है।


VAO के शो में इंटरनेट पर मौजूद सभी लेख जो VAO को स्वचालित रूप से VBO से बांधते हैं। तो, मुझे लगता है कि एक VAO एक कॉन्फ़िगरेशन है जो दोनों GlVertexAttribPointer राज्यों और glBindBuffer राज्य को धारण करता है। और हाँ, एक VBO को बांधने पर जब एक VAO बाध्य होता है तो VAO बदल जाता है। मैं यह बता रहा हूं क्योंकि मैंने यह परीक्षण किया है और यह प्रभावी रूप से करता है। यह जानकारी कहां से आई है?
मार्टिज़न कोर्टो

2
@MartijnCourteaux: " VAO के शो में इंटरनेट पर मौजूद सभी लेख जो VAO को स्वचालित रूप से VBO से जोड़ते हैं। " नहीं, वे नहीं करते हैं। शीर्ष विनिर्देश पर OpenGL विकी नहीं करता है। वास्तव में, मुझे इंटरनेट पर एक एकल लेख दिखाओ जो कहता है कि किसी भी glBindBufferराज्य को छोड़कर GL_ELEMENT_ARRAY_BUFFER एक वीएओ को बांधकर बदल दिया जाता है।
निकोल बोलस

अन्य उत्तर ने स्पष्ट किया कि कैसे glVertexAttribPointer विधि काम करती है। यह उस समय बाध्य VBO का उपयोग करता है। तुम सही हो! धन्यवाद, मैं अभी समझ गया हूं।
मार्टिग्न कोर्टको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.