2012-01-02 12 views
86

बस (मैं इतने पर पूछते हैं, चैट हैं, लेकिन यह वहाँ में मर चुका है!) यकीन है कि मैं सही ढंग से इस बात को समझ बनाना चाहते:glVertexAttribPointer स्पष्टीकरण

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

(1) में मेरी सहेजी गई है क्या मेरी समझ सही है?
documentation सबकुछ कैसे संबंधित है, इस बारे में थोड़ा सा स्पैस है।

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


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

वर्टेक्स Attrib समय glVertexAttribPointer कहा जाता है पर वर्टेक्स सरणी से जुड़ा हुआ है (3), और फिर हम सक्षम कर सकते हैं/वर्तमान में ही है किसी भी समय glEnableVertexAttribArray के माध्यम से कि attrib को निष्क्रिय है, जो शीर्ष सरणी की परवाह किए बिना?

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

उत्तर

195

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

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

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

  1. से पहले आपको किसी शेडर में उपयोग कर सकते हैं एक विशेषता सक्षम करना होगा।उदाहरण के लिए, यदि आप किसी शेडर पर शीर्ष पर भेजना चाहते हैं, तो आप इसे पहले विशेषता के रूप में भेजने की संभावना रखते हैं, 0. इसलिए प्रस्तुत करने से पहले, आपको glEnableVertexAttribArray(0); के साथ इसे सक्षम करने की आवश्यकता है।
  2. अब एक विशेषता सक्षम है, आपको उस डेटा को परिभाषित करने की आवश्यकता है जिसका उपयोग करने जा रहा है। ऐसा करने के लिए आपको अपने वीबीओ - 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,...); क्रमशः लाइटमैप निर्देशांक के लिए शिखर के लिए।

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

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

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

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

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


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

+9

"एक वेरटेक्स बफर ऑब्जेक्ट, या वीबीओ (कभी-कभी केवल एक बफर ऑब्जेक्ट के रूप में जाना जाता है)" इसे "कभी-कभी" कहा जाता है क्योंकि वास्तव में इसे कहा जाता है। यह सिर्फ एक बफर ऑब्जेक्ट है, किसी भी अन्य बफर ऑब्जेक्ट से अलग नहीं है जिसे आप वर्दी ब्लॉक, पिक्सेल ट्रांसफर, फीडबैक बदलने या किसी अन्य उपयोग के लिए उपयोग कर सकते हैं। ओपनजीएल स्पेक * कभी * किसी भी "वर्टेक्स बफर ऑब्जेक्ट" के रूप में संदर्भित नहीं करता है; यहां तक ​​कि [मूल विस्तार spec] (http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt) इसे कभी भी कॉल नहीं करता है। –

+0

उचित नामकरण से मेल खाने के लिए संपादित, धन्यवाद। –

+3

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

2

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

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

उम्मीद है कि यह मदद करता है।

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

+0

"* एक बहुत अच्छी व्याख्या के लिए ओपनजीएल-टर्मिनोलॉजी देखें। *" 1 मिनट से भी कम समय में, मुझे पहले से ही गलत जानकारी का एक टुकड़ा मिला है: "इन्हें जेनेरिक वर्टेक्स विशेषताओं के साथ एक पहचानकर्ता (इंडेक्स) जो एक शेडर वैरिएबल (कोऑर्डिनेट्स, रंग इत्यादि के लिए) से जोड़ता है जो विशेषता को संसाधित करता है। " उन्हें "इंडेक्स" नहीं कहा जाता है; वे "स्थान" हैं। यह एक बहुत ही महत्वपूर्ण भेद है क्योंकि वर्टेक्स विशेषताएँ [* भी * "इंडेक्स" हैं] (https://www.opengl.org/wiki/Program_Introspection#Attributes), जो * स्थानों से * बहुत अलग * है। यह एक बहुत ही भयानक वेबसाइट है। –

+1

यह एक उचित टिप्पणी है लेकिन पूरी तरह सटीक नहीं है। यदि आप जेनेरिक एट्रिब्यूट [glVertexAttribPointer] (https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml) को परिभाषित करने के लिए ओपनजीएल एपीआई देखते हैं, तो शून्य ग्लोर्टेक्सएट्रिबॉइंटर (ग्लूंट इंडेक्स, ग्लिंट आकार, जीएलनम टाइप, ग्लोबोलियन सामान्यीकृत, जीएलएसएज़ीई स्ट्रइड, कॉन्स जीएलवोइड * पॉइंटर) ', पहचानकर्ता को' इंडेक्स 'कहा जाता है। कार्यक्रम के संदर्भ में एक ही पहचानकर्ता को एपीआई [glGetAttribLocation] (https://www.opengl.org/sdk/docs/man/html/glGetAttribLocation.xhtml) में 'स्थान' कहा जाता है। –

संबंधित मुद्दे