2013-06-21 6 views
7

के बारे में वास्तव में कौन सी राज्य जानकारी सहेजी गई है, इस बारे में भ्रम है कि मैं ग्राफिक्स इंजन के निर्माण के दौरान arcsynthesis पर उत्कृष्ट ट्यूटोरियल्स के माध्यम से काम कर रहा हूं और पाया है कि मुझे वीएओ जितना मैंने सोचा नहीं मैंने लिया।वेरटेक्स ऐरे ऑब्जेक्ट्स - वर्तमान में बाध्य वर्टेक्स बफर

ट्यूटोरियल Chapter 5. Objects In Depth

बफर बाध्यकारी और एसोसिएशन

गुण हो सकता है आप glBindBuffer (GL_ARRAY_BUFFER) है कि सूची में नहीं है, भले ही यह प्रतिपादन के लिए विशेषता सेटअप का हिस्सा है से। GL_ARRAY_BUFFER के लिए बाध्यकारी वीएओ का हिस्सा नहीं है क्योंकि जब आप glbindBuffer (GL_ARRAY_BUFFER) को कॉल करते हैं तो बफर ऑब्जेक्ट और वर्टेक्स विशेषता के बीच संबंध तब नहीं होता है जब आप BBBBBERer (GL_ARRAY_BUFFER) को कॉल करते हैं। यह एसोसिएशन तब होता है जब आप glVertexAttribPointer को कॉल करते हैं।

जब आप glVertexAttribPointer कहते हैं, तो ओपनजीएल इस कॉल के पल में GL_ARRAY_BUFFER से जुड़ा हुआ बफर लेता है और इसे दिए गए वर्टेक्स विशेषता से जोड़ता है। GL_ARRAY_BUFFER को ग्लोबल पॉइंटर के रूप में बाध्यकारी के बारे में सोचें जो glVertexAttribPointer पढ़ता है। तो आप GlVertexAttribPointer कॉल करने के बाद GL_ARRAY_BUFFER को जो कुछ भी चाहते हैं या कुछ भी नहीं बांधने के लिए स्वतंत्र हैं; यह अंतिम प्रतिपादन में कुछ भी प्रभावित नहीं करेगा। तो वीएओ स्टोर करते हैं जो बफर ऑब्जेक्ट्स विशेषताओं से जुड़े होते हैं; लेकिन वे स्वयं को बाध्यकारी GL_ARRAY_BUFFER स्टोर नहीं करते हैं।

मैंने शुरुआत में अंतिम पंक्ति को याद किया "... लेकिन वे GL_ARRAY_BUFFER को बाध्यकारी नहीं करते हैं"। इससे पहले कि मैंने इस पंक्ति को देखा, मैंने सोचा कि वर्तमान में बाध्य बफर को सहेजा गया था जब glvertexAttribPointer को बुलाया गया था। इस ज्ञान को याद करते हुए, मैंने एक जाल वर्ग बनाया और ठीक से प्रस्तुत करने वाले कई मेष के साथ एक दृश्य प्राप्त करने में सक्षम था।

उस कोड का एक हिस्सा नीचे सूचीबद्ध है। ध्यान दें कि मैं ड्रॉ फ़ंक्शन में glBindBuffer को कॉल नहीं करता हूं।

// MESH RENDERING 

/* ...   */ 
/* SETUP FUNCTION */ 
/* ...   */ 

// Setup vertex array object 
glGenVertexArrays(1, &_vertex_array_object_id); 
glBindVertexArray(_vertex_array_object_id); 

// Setup vertex buffers 
glGenBuffers(1, &_vertex_buffer_object_id); 
glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer_object_id); 
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(vertex), &_vertices[0], GL_STATIC_DRAW); 

// Setup vertex attributes 
glEnableVertexAttribArray(e_aid_position); 
glEnableVertexAttribArray(e_aid_normal); 
glEnableVertexAttribArray(e_aid_color); 
glEnableVertexAttribArray(e_aid_tex); 

glVertexAttribPointer(e_aid_position, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, pos)); 
glVertexAttribPointer(e_aid_normal, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, norm)); 
glVertexAttribPointer(e_aid_color, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, col)); 
glVertexAttribPointer(e_aid_tex,  2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)offsetof(vertex, tex)); 

/* ...   */ 
/* DRAW FUNCTION */ 
/* ...   */ 

glBindVertexArray(_vertex_array_object_id); 
glDrawArrays(GL_TRIANGLES, 0, _vertices.size()); 

अब मैं के बारे में प्रकाश मैं कुछ डिबग ड्राइंग तो मैं अपने सभी normals सही हैं सत्यापित कर सकता प्राप्त करना चाहता था शुरू करने के लिए कर रहा हूँ कि। वर्तमान में मैं सिर्फ वेक्टर में एक फ्रेम के लिए प्रस्तुत करने के लिए सभी लाइनों को स्टोर करता हूं। चूंकि यह डेटा प्रत्येक फ्रेम को बदलने की संभावना है, इसलिए मैं GL_DYNAMIC_DRAW का उपयोग कर रहा हूं और इसे प्रस्तुत करने से पहले डेटा निर्दिष्ट करता हूं।

प्रारंभ में जब मैंने ऐसा किया तो मुझे कचरा लाइनें मिलेंगी जो केवल अनंतता में इंगित होंगी। अपमानजनक कोड के नीचे है:

// DEBUG DRAW LINE RENDERING 

/* ...   */ 
/* SETUP FUNCTION */ 
/* ...   */ 

// Setup vertex array object 
glGenVertexArrays(1, &_vertex_array_object_id); 
glBindVertexArray(_vertex_array_object_id); 

// Setup vertex buffers 
glGenBuffers(1, &_vertex_buffer_object_id); 
glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer_object_id); 
    // Note: no buffer data supplied here!!! 

// Setup vertex attributes 
glEnableVertexAttribArray(e_aid_position); 
glEnableVertexAttribArray(e_aid_color); 

glVertexAttribPointer(e_aid_position, 3, GL_FLOAT, GL_FALSE, sizeof(line_vertex), (GLvoid*)offsetof(line_vertex, pos)); 
glVertexAttribPointer(e_aid_color, 4, GL_FLOAT, GL_FALSE, sizeof(line_vertex), (GLvoid*)offsetof(line_vertex, col)); 

/* ...   */ 
/* DRAW FUNCTION */ 
/* ...   */ 

glBindVertexArray(_vertex_array_object_id); 
    // Specifying buffer data here instead!!! 
glBufferData(GL_ARRAY_BUFFER, _line_vertices.size() * sizeof(line_vertex), &_line_vertices[0], GL_DYNAMIC_DRAW); 
glDrawArrays(GL_LINES, 0, _line_vertices.size()); 

शिकार का एक सा होने के बाद, साथ ही विस्तार मैं ऊपर याद किया, मैंने पाया है कि अगर मैं ड्रॉ समारोह में glBufferData से पहले glBindBuffer कहते हैं, सब कुछ ठीक से काम करता है खोजने।

मैं उलझन में हूं कि क्यों मेरे जाल प्रतिपादन ने इसे पहले स्थान पर क्यों काम किया। अगर मैं बफर में डेटा बदलता हूं तो क्या मुझे केवल glbindBuffer को कॉल करने की आवश्यकता है? या व्यवहार अपरिभाषित है यदि आप बफर को बांध नहीं पाते हैं और मैं बस दुर्भाग्यपूर्ण था और क्या यह काम करता था?

ध्यान दें कि मैं OpenGL संस्करण 3.0 को लक्षित कर रहा हूं।

उत्तर

10

मैं केवल glBindBuffer फिर से कॉल करने के लिए अगर मैं बफर में डेटा को बदलने की जरूरत है?

हाँ, VAO वस्तु को याद रखता है जो बफ़र्स, हर बार जब आप whilst कि VAO ही था glVertexAttribPointer कहा जाता है बाध्य कर रहे थे तो आप आमतौर पर glBindBuffer फिर से फोन की जरूरत नहीं है। यदि आप बफर में डेटा को बदलना चाहते हैं, तो ओपनजीएल को यह पता होना चाहिए कि आप कौन सा बफर बदल रहे हैं, इसलिए आपको glBufferData पर कॉल करने से पहले glBindBuffer पर कॉल करने की आवश्यकता है। यह अप्रासंगिक है कि वीएओ वस्तु इस बिंदु पर बंधी हुई है।

+2

ठीक है, यह अधिक समझ में आता है। मेरे पास एक मामूली जानकारी है कि मैं अभी भी थोड़ा अस्पष्ट हूं। आइए मान लें कि मैं VAO 1 के साथ glBindVertexArray को कॉल करता हूं जो याद करता है कि VV 1 को बाध्य किया गया था जब glVertexAttribPointer को बुलाया गया था। तब मैं ग्लोब बाइफर को वीबीओ 2 के साथ कॉल करता हूं, उसके बाद glDrawArrays। कौन सा बफर इस्तेमाल किया जाना चाहिए, वीबीओ 1 या वीबीओ 2? मुझे विश्वास नहीं है कि यह ऐसा कुछ है जो सामान्य रूप से करता है, मैं बस यह सुनिश्चित करना चाहता हूं कि मैं समझ रहा हूं कि क्या हो रहा है। –

+2

वीबीओ 1 का उपयोग किया जाएगा। ध्यान दें कि यह सच है कि आप वीएओ का उपयोग कर रहे हैं या नहीं। इसके अलावा आप कई वीबीओ बाध्य कर सकते हैं जबकि आपके पास वीएओ बाध्य था (शायद प्रत्येक विशेषता के लिए एक अलग)। एक बार जब आप glvertexAttribPointer को बुलाते हैं तो उस समय बफर बाध्य होता है जिसका उपयोग किया जाएगा। – GuyRT

+1

बहुत बढ़िया, यह जानना अच्छा है! स्पष्टीकरण के लिए धन्यवाद एक टन! –

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