2012-01-14 16 views
7

मैं इस सवाल से आया था:वीएओ/वीबीओ की ओपनजीएल संरचना?

opengl vbo advice

मैं ओपन 3.3 का उपयोग करें और पदावनत सुविधाओं का उपयोग करने नहीं होंगे। मैं अपने ब्लेंडर मॉडल आयात करने के लिए असिंप का उपयोग कर रहा हूँ। लेकिन मैं थोड़ा उलझन में हूं कि वीएओ और वीबीओ के संदर्भ में मुझे उन्हें कितना विभाजित करना चाहिए।

पहले थोड़ा सा सवाल पूछें। मैं glDrawElements का उपयोग करता हूं, इसका मतलब है कि मैं अपने वर्टेक्स विशेषताओं को अंतःस्थापित नहीं कर सकता या क्या VAO glvertexAttribPointer का उपयोग करके पता लगा सकता है और glderawElements ऑफसेट देख सकता है कि मेरी चरम स्थिति कहां है?

मुख्य प्रश्न मुझे लगता है कि मैं अपने वीएओ/वीबीओ को एक मॉडल के लिए कई चलती भागों, और एकाधिक मेष पीआर के साथ कैसे ढूढ़ूं। अंश।

गधे में प्रत्येक नोड में कई मेष हो सकते हैं जहां प्रत्येक जाल में बनावट, शिखर, मानक, सामग्री इत्यादि होते हैं। गधे में नोड्स में परिवर्तन होते हैं। कहो कि मेरे पास एक तोप बुर्ज के साथ एक जहाज है। मैं बुर्ज को घुमाने में सक्षम होना चाहता हूं। इसका मतलब यह है कि मैं जहाज को अपने गुणों (या एकाधिक वीबीओ इत्यादि) वाले प्रत्येक जाल के लिए वीबीओ के साथ एक अलग वीएओ बना दूंगा। मैं यह जाता है

तरह
draw(ship); //call to draw ship VAO 
pushMatrix(turretMatrix) //updating uniform modelview matrix for the shader 
draw(turret); //call to draw turret VAO 

मैं पूरी तरह से UBO (वर्दी बफर वस्तुओं) अभी तक समझ में नहीं आता है लगता है, लेकिन यह मैं कई वर्दी में पारित कर सकते हैं लगता है, कि मदद मिलेगी मुझे एक में जंगम भागों के साथ एक पूर्ण मॉडल शामिल एकल वीएओ?

उत्तर

13

पहले, वीएओ से पहले अंतिम वर्टेक्स विशेषता बाइंडिंग ("एक सूचकांक बफर (GL_ELEMENT_ARRAY_BUFFER_BINDING) के लिए वीबीओ बाध्यकारी केवल" याद करता है ", यदि कोई है तो)। तो glDrawElements() में ऑफ़सेट को याद नहीं है, आपको वीएओ का उपयोग करते समय बाद में कॉल करने की आवश्यकता है। यह laso आप interleaved vertex सरणी का उपयोग करने से नहीं रोकता है। मुझे समझाने की कोशिश करते हैं:

int vbo[3]; 
glGenBuffers(3, vbo); 
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); 
glBufferData(GL_ARRAY_BUFFER, data0, size0); 
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); 
glBufferData(GL_ARRAY_BUFFER, data1, size1); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data2, size2); 
// create some buffers and fill them with data 

int vao; 
glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 
// create a VAO 

{ 
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO 
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), NULL); // this is VAO saved state 
    glEnableVertexAttribArray(0); // this is VAO saved state 
    // sets up one vertex attrib array from vbo[0] (say positions) 

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); // not saved in VAO 
    glVertexAttribPointer(1, 3, GL_FLOAT, false, 5 * sizeof(float), NULL); // this is VAO saved state 
    glVertexAttribPointer(2, 2, GL_FLOAT, false, 5 * sizeof(float), (const void*)(2 * sizeof(float))); // this is VAO saved state 
    glEnableVertexAttribArray(1); // this is VAO saved state 
    glEnableVertexAttribArray(2); // this is VAO saved state 
    // sets up two more VAAs from vbo[1] (say normals interleaved with texcoords) 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]); // this is VAO saved state 
    // uses the third buffer as the source for indices 
} 
// set up state that VAO "remembers" 

glBindVertexArray(0); // bind different vaos, etc ... 

बाद में ...

glBindVertexArray(vao); // bind our VAO (so we have VAAs 0, 1 and 2 as well as index buffer) 
glDrawElements(GL_TRIANGLE_STRIP, 57, GL_UNSIGNED_INT, NULL); 
glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_INT, (const void*)(57 * sizeof(unsigned int))); 
// draws two parts of the mesh as triangle strips 

तो आप देख ... आप glDrawElements का उपयोग कर interleaved शिखर सरणियों एक भी VAO और एक या अधिक VBOs का उपयोग कर बना सकते हैं।

अपने प्रश्न के दूसरे भाग का उत्तर देने के लिए, या तो जाल के विभिन्न हिस्सों के लिए अलग-अलग वीएओ और वीबीओ हो सकते हैं (इसलिए अलग-अलग हिस्सों को चित्रित करना आसान है), या आप सभी को एक वीएओ वीबीओ जोड़ी में फ्यूज कर सकते हैं (इसलिए आपको आवश्यकता है glBind*() को अक्सर कॉल न करें) और जाल के अलग-अलग हिस्सों को आकर्षित करने के लिए एकाधिक glDraw*() कॉल का उपयोग करें (जैसा कि ऊपर दिए गए कोड में देखा गया है - कल्पना करें कि पहले glDrawElements() जहाज खींचता है और दूसरा बुर्ज खींचता है, आप बस कॉल के बीच कुछ मैट्रिक्स वर्दी अपडेट करते हैं)।

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

वर्दी बफर ऑब्जेक्ट्स के रूप में जाना जाता है, केवल एक ही फायदा यह है कि आप उनमें बहुत सारे डेटा पैक कर सकते हैं और उन्हें आसानी से शेडर्स के बीच साझा किया जा सकता है (बस यूबीओ को किसी भी शेडर को बाध्य करने के लिए बाध्य करें)। आपके लिए उनका उपयोग करने में कोई वास्तविक लाभ नहीं है, सिवाय इसके कि यदि आपके पास matrices के 1OOOs के साथ ऑब्जेक्ट्स हों।

इसके अलावा, मैंने स्मृति से उपरोक्त स्रोत कोड लिखे हैं। मुझे पता है अगर वहाँ कुछ त्रुटियों/समस्याएं हैं करते हैं ...

+0

कूल मुझे लगता है कि मैं इसे interleaving के साथ मिलता है, इसे आजमा देना है। लेकिन मुझे लगता है कि आपने यह सुनिश्चित करने के लिए गलती की है कि पहले glvertexAttribPointer को कशेरुक पदों के लिए डिफॉल्ट करने में, जैसा कि मैंने समझा है कि वर्टेक्स पदों को vbo [0] में कसकर पैक किया गया है, फिर भी आपने इसे एक रास्ता दिया है? पदों के लिए आगे शून्य नहीं होना चाहिए क्योंकि वे interleaved नहीं हैं। – CodeMonkey

+0

मुझे शेडर में जाल आईडी के बारे में विचार पसंद है और इसे एक विशेषता के रूप में पास किया गया है, लेकिन मैं शेडर (जैसे वर्दी सरणी) में कई मैट्रिक्स में पार्सिंग के बारे में कैसे जाउंगा? क्या यह है जहां मैं यूबीओ का उपयोग 10 अलग-अलग टर्रेट्स के लिए 10 अलग-अलग रूपांतरण मैट्रिक्स कह सकता हूं और शेडर के अंदर सही मैट्रिक्स को देखने के लिए एक विशेषता के रूप में विश्लेषण किए गए इंडेक्स का उपयोग कर सकता हूं? यह मुझे एक पूरे जहाज को एक साथ जाने के साथ पूरे जहाज को चित्रित करने वाले glmultiDrawElements/Arrays फ़ंक्शंस का उपयोग करने में सक्षम बनाता है? – CodeMonkey

+0

हाय, घुमावदार के साथ अच्छा अवलोकन। लेकिन यह एक त्रुटि नहीं है। या तो मैं आगे 0 छोड़ सकता हूं और ओपनजीएल जानता है (दूसरे और तीसरे तर्क से) कि मेरे पास 3 डी जीएल_एफएलएटीएस की धारा है (और इसलिए आकार 3 * आकार (फ्लोट) है), या मैं इसके लिए आगे की गणना कर सकता हूं। इसके साथ कुछ भी गलत नहीं है। आगे स्पष्टीकरण के लिए - लगातार दो अक्षरों के पते के बीच दूरी है, यह उनके बीच की जगह नहीं है (इसलिए 0 का मतलब यह नहीं है कि शिखर के बीच कोई अप्रयुक्त बाइट नहीं है, इसका मतलब है कि ओपनजीएल को आयामों की संख्या से असली प्रगति की गणना करनी चाहिए और डेटा प्रकार का इस्तेमाल किया)। –

0

@theswine

नहीं VAO आरंभीकरण के दौरान इस बंधन के क्रैश होने का मेरा कार्यक्रम का कारण बनता है, लेकिन VAO बंधन के बाद यह बाध्यकारी इसे सही ढंग से चलाने के लिए कारण बनता है। क्या आप वाकई वीएओ में सहेजे नहीं गए हैं?

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO 

(Btw:! खेद एक पुराने विषय को लाने के लिए, मैं सिर्फ यह दूसरों के लिए उपयोगी, इस पोस्ट यकीन था (जो मुझे याद दिलाता है, धन्यवाद हो सकता है सोचा था !!))

+0

हाय। मैंने इसे दुर्घटना से देखा है, क्योंकि जब आप उत्तर पोस्ट करते हैं तो उपयोगकर्ता को सूचित नहीं किया जाता है, '@ login' से शुरू होता है (केवल ओपी को इसके बारे में अधिसूचित किया जाता है)। आपको मेरे जवाब में एक टिप्पणी छोड़नी चाहिए, मुझे इसकी अधिसूचना दी जाएगी। मेरा सुझाव है कि आप एक नया प्रश्न शुरू करें और कुछ न्यूनतम कोड पोस्ट करें जो आपके दुर्घटना को पुन: उत्पन्न करता है। क्या यह संभव होगा? फिर आप मुझे इस टिप्पणी के नीचे एक '@ लॉगिन' टिप्पणी छोड़ सकते हैं और मैं आपकी समस्या को देखूंगा। –

+0

इसके बारे में क्षमा करें, मैं आपकी प्रतिष्ठा की कमी के कारण आपकी पोस्ट पर टिप्पणी करने में असमर्थ था। लेकिन बीमार जांचने के लिए आपके साथ कुछ फेंकने की कोशिश करें (शायद यह सिर्फ मेरा हार्डवेयर?) – luveti

+0

यह आमतौर पर केवल एक स्वैप इंडेक्स या उलझन में बाध्यकारी होता है। सबसे अच्छा होता है। कभी-कभी, तत्व सरणी (अनुक्रमणिका) बफर समस्याएं बनाती है, खासकर इंटेल ग्राफिक्स कार्ड पर। –