glVertexAttribPointer स्पष्टीकरण


94

बस यह सुनिश्चित करना चाहता हूं कि मैं इसे सही ढंग से समझूं (मैं एसओ चैट पर पूछूंगा, लेकिन यह वहां मर चुका है!)।

हमें एक वर्टेक्स एरियर मिला है, जिसे हम इसे
बाइंड करके "करंट" बनाते हैं, फिर हमें एक बफर मिला है, जिसे हम एक टारगेट से बाँधते हैं,
फिर हम उस टारगेट को भरते हैं, glBufferData जिसके ज़रिए जो भी उस टारगेट से जुड़ा होता है, यानी हमारा बफर
और फिर हम कॉल करते हैं glVertexAttribPointerजो बताता है कि डेटा कैसे निर्धारित किया गया है - डेटा जो कुछ भी है उसके लिए बाध्य है GL_ARRAY_BUFFER और यह विवरणकर्ता हमारे मूल शीर्ष सरणी में सहेजा गया है

(१) क्या मेरी समझ सही है? प्रलेखन सब कुछ कैसे संबद्ध के बारे में थोड़ा विरल है।

(२) क्या किसी प्रकार का डिफ़ॉल्ट वर्टेक्स एरे है? क्योंकि मैं भूल गया / छोड़े गए glGenVertexArraysऔर glBindVertexArrayऔर मेरे कार्यक्रम के बिना यह ठीक काम किया।


संपादित करें: मैं एक कदम याद किया ... glEnableVertexAttribArray

(३) क्या वर्टेक्स एरीब को उस समय के वर्टेक्स एरे के साथ जोड़ा glVertexAttribPointerजाता है, और तब हम glEnableVertexAttribArrayकिसी भी समय उस एट्रिब को सक्षम / अक्षम कर सकते हैं , जिसकी परवाह किए बिना वर्टेक्स एरे वर्तमान में बाध्य है?

या (3 बी) क्या वर्टेक्स एट्रिब को उस समय के वर्टेक्स एरे के साथ glEnableVertexAttribArrayजोड़ा जाता है, और इस प्रकार हम एक ही वर्टेक्स एट्रिब को glEnableVertexAttribArrayअलग-अलग समय पर कॉल करके कई वर्टेक्स एररेज़ में जोड़ सकते हैं , जब अलग-अलग वर्टेक्स एरियर्स बाध्य होते हैं?

जवाबों:


210

शब्दावली में से कुछ बंद है:

  • A Vertex Arrayकेवल एक सरणी (आमतौर पर float[]) है जिसमें वर्टेक्स डेटा है। इसके लिए किसी चीज से बंधने की जरूरत नहीं है। एक Vertex Array Objectया वीएओ के साथ भ्रमित होने की नहीं , जो मैं बाद में जाऊंगा
  • एक Buffer Object, आमतौर पर एक के रूप में भेजा Vertex Buffer Objectजब कोने भंडारण, या संक्षेप में VBO, क्या तुम सिर्फ एक कॉल कर रहे है Buffer
  • वर्टेक्स ऐरे में कुछ भी सहेजा नहीं जाता है, glVertexAttribPointerठीक वैसे ही काम करता है glVertexPointerया glTexCoordPointerकाम करता है , नामांकित विशेषताओं के बजाय, आपको एक नंबर प्रदान करना है जो आपकी स्वयं की विशेषता को निर्दिष्ट करता है। आप इस मान से गुजरते हैं indexglVertexAttribPointerजब आप कॉल करते हैं glDrawArraysया अगली बार आपके सभी कॉल कतारबद्ध हो जाते हैं glDrawElements। यदि आपके पास एक VAO है, तो VAO आपकी सभी विशेषताओं के लिए सेटिंग्स संग्रहीत करेगा।

यहाँ मुख्य मुद्दा यह है कि आप VAOs के साथ वर्टेक्स विशेषताओं को भ्रमित कर रहे हैं। वर्टेक्स विशेषताएँ ड्राइंग के लिए वर्टीकल, टेक्सकोर्ड्स, नॉर्म्सल्स आदि को परिभाषित करने का नया तरीका हैं। VAO स्टोर राज्य। मैं सबसे पहले यह बताने जा रहा हूं कि ड्राइंग वर्टेक्स विशेषताओं के साथ कैसे काम करती है, फिर समझाएं कि कैसे आप वीएओ के साथ विधि कॉल की संख्या में कटौती कर सकते हैं:

  1. इससे पहले कि आप किसी shader में इसका उपयोग कर सकें, आपको एक विशेषता सक्षम करनी होगी। उदाहरण के लिए, यदि आप किसी शेडर को वर्टिकल भेजना चाहते हैं, तो आप सबसे पहले इसे पहली विशेषता के रूप में भेजने की संभावना रखते हैं। 0. इसलिए रेंडर करने से पहले आपको इसे सक्षम करना होगा glEnableVertexAttribArray(0);
  2. अब जब एक विशेषता सक्षम हो गई है, तो आपको उस डेटा को परिभाषित करने की आवश्यकता है जो इसका उपयोग करने जा रहा है। ऐसा करने के लिए आपको अपने VBO को बांधने की आवश्यकता है - glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
  3. और अब हम विशेषता को परिभाषित कर सकते हैं - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);। पैरामीटर के क्रम में: 0 वह विशेषता है जिसे आप परिभाषित कर रहे हैं, 3 प्रत्येक शीर्ष का आकार GL_FLOATहै, प्रकार है, GL_FALSEप्रत्येक शीर्ष को सामान्य नहीं करने का अर्थ है, अंतिम 2 शून्य का मतलब है कि कोई स्ट्राइड या कोने पर ऑफसेट नहीं है।
  4. इसके साथ कुछ ड्रा करें - glDrawArrays(GL_TRIANGLES, 0, 6);
  5. आपके द्वारा आकर्षित की जाने वाली अगली चीज़ विशेषता 0 का उपयोग नहीं कर सकती है (वास्तविक रूप से यह होगा, लेकिन यह एक उदाहरण है), इसलिए हम इसे अक्षम कर सकते हैं - glDisableVertexAttribArray(0);

लपेटें कि glUseProgram()कॉल में और आपके पास एक रेंडरिंग सिस्टम है जो शेड्स के साथ ठीक से काम करता है। लेकिन मान लें कि आपके पास 5 अलग-अलग विशेषताएँ, कोने, टेक्सकोर्ड, मानदंड, रंग और लाइटमैप निर्देशांक हैं। सबसे पहले, आप glVertexAttribPointerइनमें से प्रत्येक विशेषता के लिए एक कॉल कर रहे हैं, और आपको पहले से सभी विशेषताओं को सक्षम करना होगा। मान लीजिए कि आपने एट्रिब्यूट 0-4 को परिभाषित किया है क्योंकि मैंने उन्हें सूचीबद्ध किया है। आप उन सभी को इस तरह से सक्षम करेंगे:

for (int i = 0; i < 5; i++)
    glEnableVertexAttribArray(i);

और फिर आप प्रत्येक विशेषता के लिए अलग VBOs बाध्य करने के लिए (जब तक आप उन सब को एक VBO और उपयोग ऑफसेट / कदम में स्टोर) के लिए होता है, तो आप 5 अलग अलग करने की जरूरत है glVertexAttribPointerकॉल से, glVertexAttribPointer(0,...);करने के लिए glVertexAttribPointer(4,...);क्रमश: lightmap निर्देशांक के कोने के लिए।

उम्मीद है कि प्रणाली अकेले समझ में आता है। अब मैं इस प्रकार के प्रतिपादन करते समय विधि कॉल की संख्या में कटौती करने के लिए उनका उपयोग करने के तरीके के बारे में बताने के लिए VAO पर आगे बढ़ने जा रहा हूँ। ध्यान दें कि VAO का उपयोग करना आवश्यक नहीं है।

एक Vertex Array Objectया वीएओ का उपयोग सभी glVertexAttribPointerकॉल की स्थिति और वीबीओ को संग्रहीत करने के लिए किया जाता है जो प्रत्येक glVertexAttribPointerकॉल किए जाने पर लक्षित थे।

आप एक कॉल के साथ उत्पन्न करते हैं glGenVertexArrays। एक VAO में आपको जो कुछ भी ज़रूरत है उसे स्टोर करने के लिए, इसके साथ बाँधें glBindVertexArray, फिर एक पूर्ण ड्रॉ कॉल करें । सभी ड्रा बाइंड कॉल वीएओ द्वारा इंटरसेप्ट और स्टोर किए जाते हैं। आप के साथ VAO को रद्द कर सकते हैंglBindVertexArray(0);

अब जब आप ऑब्जेक्ट को आकर्षित करना चाहते हैं, तो आपको सभी VBO बाइंड या कॉल को फिर से कॉल करने की आवश्यकता नहीं है glVertexAttribPointer, आपको बस VAO को glBindVertexArrayतब कॉल करने की आवश्यकता है glDrawArraysया glDrawElementsआप ठीक उसी चीज़ को आरेखित करेंगे जैसे कि आप उन सभी विधि कॉल कर रहे थे। आप शायद VAO को भी बाद में अनबाइंड करना चाहते हैं।

एक बार जब आप VAO को अनबॉन्ड कर देते हैं, तो सभी राज्य आपके द्वारा VAO को बाध्य करने से पहले की स्थिति में वापस आ जाते हैं। मुझे यकीन नहीं है कि अगर कोई बदलाव किया जाता है जबकि VAO बाध्य है, लेकिन यह आसानी से एक परीक्षण कार्यक्रम के साथ पता लगाया जा सकता है। मुझे लगता है कि आप glBindVertexArray(0);"डिफ़ॉल्ट" VAO के लिए बाध्यकारी के रूप में सोच सकते हैं ...


अद्यतन: किसी ने मेरे ध्यान में वास्तविक ड्रॉ कॉल की आवश्यकता को लाया। जैसा कि यह पता चला है, आपको वास्तव में VAO की स्थापना करते समय एक पूर्ण ड्रा कॉल करने की आवश्यकता नहीं है, बस सभी बाध्यकारी सामान। पता नहीं क्यों मुझे लगा कि यह पहले आवश्यक था, लेकिन यह अब तय हो गया है।


10
"एक वर्टेक्स बफर ऑब्जेक्ट, या वीबीओ (कभी-कभी इसे सिर्फ एक बफर ऑब्जेक्ट के रूप में संदर्भित किया जाता है)" यह "कभी-कभी" कहा जाता है, क्योंकि यह वास्तव में है जिसे यह कहा जाता है। यह सिर्फ एक बफर ऑब्जेक्ट है, किसी भी अन्य बफर ऑब्जेक्ट से अलग नहीं है जिसे आप यूनिफ़ॉर्म ब्लॉक, पिक्सेल ट्रांसफर, ट्रांसफ़ॉर्म फीडबैक या किसी अन्य उपयोग के लिए उपयोग कर सकते हैं। OpenGL युक्ति कभी भी "वर्टेक्स बफर ऑब्जेक्ट" के रूप में किसी भी चीज़ को संदर्भित नहीं करता है; यहां तक ​​कि मूल विस्तार कल्पना भी इसे कभी नहीं कहती है।
निकोल बोलस

3
बहुत बढ़िया जवाब। इसे लिखने के लिए समय निकालने के लिए धन्यवाद! एक युगल हालांकि सवालों का पालन करता है: (1) आपने कहा "रेंडर करने से पहले, और इससे पहले कि आप विशेषता को परिभाषित करें, आपको इसे glEnableVertexAttribArray (0) के साथ सक्षम करने की आवश्यकता है" - क्या आपको यकीन है कि कॉल करने से पहले इसे सक्षम करने की आवश्यकता है glVertexAttribPointer? मेरे परीक्षणों में, आदेश कोई बात नहीं लगती है। (२) अगर मैं आपको सही तरीके से समझूं, तो वर्टेक्स एट्रीब्यूट वैश्विक हैं, और केवल उनकी सक्षम / अक्षम स्थिति ही वर्तमान में VAO के लिए बचाई गई है?
एमपीएन

1
(1) मुझे नहीं लगता कि आदेश मायने रखता है, जब तक कि आपने इसे पहले सक्षम किया है glDrawArraysया glDrawElements। मैं उस पोस्ट को प्रतिबिंबित करने के लिए अपडेट करूंगा (2) हां, लेकिन यह केवल सक्षम / अक्षम स्थिति नहीं है जो संग्रहीत है, यह उन कॉलों से संबंधित सब कुछ है - उस समय GL_ARRAY_BUFFER के लिए बाध्य था, प्रकार, स्ट्राइड और ऑफ़सेट। अनिवार्य रूप से यह सभी वेरटेक्स एट्रीब्यूट्स को बदलने के लिए पर्याप्त भंडारण कर रहा है जिस तरह से आप उन्हें VAO के साथ सेट करते हैं।
रॉबर्ट रूहानी

2
हाँ, VAO आपको एक VAO बांधने के साथ अधिकांश ड्रॉ पद्धति को बदलने के लिए डिज़ाइन किया गया है। हर इकाई का एक अलग VAO हो सकता है और यह अभी भी ठीक काम करेगा। आपको अभी भी वर्दी अद्यतन करना होगा और अपने स्वयं के बनावट को बांधना होगा। और आपको एक ही विशेषता अनुक्रमित का उपयोग करना होगा क्योंकि आपको अपने shader की विशेषताओं को विशेषता सूचकांकों के साथ बाँधना होगा, चाहे वह layout(location = x)shader में हो या shader glBindAttributeLocationसंकलित करते समय। उदाहरण
राबर्ट रूहानी

8
ध्यान दें कि आधुनिक ओपनजीएल में कोई डिफ़ॉल्ट वर्टेक्स ऐरे ऑब्जेक्ट नहीं है, आपको स्वयं एक बनाना होगा या आपका एप्लिकेशन आगे-संगत संदर्भ में काम नहीं करेगा।
ओवरव्यू

3

एपीआई की शब्दावली और अनुक्रम कहा जाता है वास्तव में काफी भ्रामक है। क्या और भी अधिक भ्रामक है कि कैसे विभिन्न पहलुओं - बफर, जेनेरिक वर्टेक्स विशेषता और शेडर विशेषता चर जुड़े हुए हैं। बहुत अच्छी व्याख्या के लिए ओपनजीएल-शब्दावली देखें ।

इसके अलावा, लिंक OpenGL-VBO, shader, VAO आवश्यक API कॉल के साथ एक सरल उदाहरण दिखाता है। यह विशेष रूप से उन लोगों के लिए अच्छा है, जो तत्काल मोड से प्रोग्रामेबल पाइपलाइन तक संक्रमण कर रहे हैं।

आशा करता हूँ की ये काम करेगा।

संपादित करें: जैसा कि आप नीचे दी गई टिप्पणियों से देख सकते हैं, लोग अनुमान लगा सकते हैं और निष्कर्ष पर जा सकते हैं। वास्तविकता यह है कि यह शुरुआती लोगों के लिए काफी भ्रामक है।


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

2
यह एक उचित टिप्पणी है लेकिन पूरी तरह से सही नहीं है। आप एक सामान्य विशेषता परिभाषित करने के लिए ओपन एपीआई को देखें, तो glVertexAttribPointer , void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer), पहचानकर्ता के रूप में जाना जाता है index। कार्यक्रम के संदर्भ में समान पहचानकर्ता locationको एपीआई glGetAttribLocation में कहा जाता है ।
एपी-ओएसडी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.