2011-09-05 15 views
6

मैं ओपनजीएल ईएस 2.0 में वर्टेक्स बफर ऑब्जेक्ट (वीबीओ) का उपयोग कर रहा हूं।ओपनजीएल ईएस 2.0: GL_STREAM_DRAW के साथ एक वीबीओ के लिए सबसे कुशल सेटअप?

मेरे पास वर्टेक्स डेटा का एक सेट है जो सामान्य RAM में स्थायी रूप से संग्रहीत होता है। इसका कारण यह है कि स्क्रैच से कशेरुक पदों की गणना करना महंगी है, लेकिन सस्ता अपडेट करने के लिए अंतिम स्थिति में एक डेल्टा जोड़ा जा सकता है।

समय के साथ तेजी से बदलाव किए जाने वाले शिखरों की वास्तविक संख्या में बदलाव आया है। एक फ्रेम में मेरे पास 1000 और अगले 2500 में हो सकता है। पहले यहां प्राप्त सलाह के बाद, अब मैं पूर्णांक UPPER को ऊर्ध्वाधर की संख्या पर ऊपरी बाउंड के रूप में निर्दिष्ट करता हूं जो कभी भी खींचा जाएगा। मैं malloc इस वर्ट पर आधारित स्टार्टअप पर केवल एक बार मेरी वर्टेक्स और इंडेक्स डेटा सरणी।

मैं GL_STREAM_DRAW प्रत्येक glBindBuffer पर संकेत संकेत देता हूं ताकि प्रत्येक फ्रेम में डेटा को इंगित करने के लिए कॉल किया जा सके।

संभव के रूप में कुशल होने का प्रयास कर रहा है, मैं निम्नलिखित सेटअप बनाया:

// SETUP: Called only once. 
glBindBuffer(GL_ARRAY_BUFFER,...); 
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for UPPER vertices. 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (UPPER-1). 
glEnableVertexAttribArray(...); // Setup vertex attributes. 
glVertexAttribPointer(...); 
glUseProgram(...); // Use program with custom shaders. 
glUniformMatrix4fv(...); // Identify shader uniforms. 

// UPDATE: Called when vertex data changes (on each frame). 
glBindBuffer(GL_ARRAY_BUFFER,...); 
glBufferSubData(GL_ARRAY_BUFFER,...); // Update VBO data. 

// RENDER: Called on each frame. 
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...); // Number of vertices and indices to be used is inherently specified in here. 

हालांकि इस glDrawElements पर एक EXC_BAD_ACCESS साथ टूट जाता है, और मुझे पता है कि यह gl आदेशों की मेरी आदेश की वजह से है।

मैं इसी तरह की स्थापना के पहले जो काम किया:

// UPDATE: Called when vertex data changes (on each frame). 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (actual number of vertices to draw - 1) 

// RENDER: Called on each frame. 
glBindBuffer(GL_ARRAY_BUFFER,...); 
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for actual number of vertices (not UPPER). 
glEnableVertexAttribArray(...); // Setup vertex attributes. 
glVertexAttribPointer(...); 
glUseProgram(...); // Use program with custom shaders. 
glUniformMatrix4fv(...); // Identify shader uniforms. 
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...); 

हालांकि, इस स्थापना फ्रेम प्रति और अधिक मेहनत करनी होगी और जैसा कि आप UPPER VBO आकार में परिवर्तन देख सकते हैं (क्योंकि यह वास्तविक आकार का उपयोग करता है, नहीं), जो मुझे बताया गया है एक बड़ा प्रदर्शन नाली है।

क्या कोई मुझे मेरे नए सेटअप के साथ किसी भी स्पष्ट समस्या की व्याख्या कर सकता है, और सबसे महत्वपूर्ण बात यह है कि मैं कोglDrawElements से पहले प्रत्येक फ्रेम पर कॉल करता हूं? मेरी धारणा है कि मैं सभी संभावित सूचकांक अग्रिम में तैयार कर सकता हूं और फिर वास्तविक वर्टेक्स गिनती glDrawElements को स्पष्ट रूप से गलत कर सकता हूं।

+1

[ओपनजीएल ईएस 2.0: संभवतः वीबीओ के साथ glDrawElements के पहले आवश्यक कमांड] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/7302562/opengl-es-2-0-commands-required-just-before-gldrawelements- साथ-vbo)। एक पूरी तरह से अलग सवाल पूछने के शीर्षक के बावजूद, वास्तविक पाठ प्रदर्शन या दक्षता में रुचि नहीं है। यह वही सवाल पूछ रहा है जो उसने कल किया था। –

+0

आपको उस विवरण को अपने मूल प्रश्न में जोड़ना चाहिए था, न कि नया बनाया। –

+0

मेरे पास मुश्किल से कोई नींद नहीं है और मैं एक बुरे मूड में हूं, जिसके लिए मैं क्षमा चाहता हूं। निष्पक्ष होने के लिए, आपकी कुछ टिप्पणियां बहुत ही तेज लगती हैं। फिर भी, आपके उत्तर ने मुझे अपनी समस्या को ठीक करने की अनुमति दी है, और मैं इसके लिए बहुत आभारी हूं। धन्यवाद। – KomodoDave

उत्तर

9

आपके प्रश्न शीर्षक में पूछे गए प्रश्न का उत्तर देने के लिए, वर्टेक्स डेटा स्ट्रीमिंग के लिए कोई "सबसे कुशल" बफर ऑब्जेक्ट सेटअप नहीं है। विशेष रूप से ईएस 2.0 पर नहीं, जिसमें विभिन्न हार्डवेयर की विस्तृत रेंज शामिल है, प्रत्येक अपनी विशिष्टताओं के साथ।

आपके प्रश्न का उत्तर देने के बारे में आपके प्रश्न का उत्तर देने के लिए, ऐसा संभव है क्योंकि आप वास्तव में इन कार्यों का सम्मान नहीं कर रहे हैं।

उदाहरण के लिए, glUseProgram दिया कार्यक्रम वस्तु का कारण बनता है कार्यक्रम उद्देश्य यह है कि किसी भी बाद glDraw* कॉल का उपयोग करेगा जब तक आप glUseProgram फिर से फोन बन जाते हैं। अधिकांश ओपनजीएल कार्यों के बारे में सोचें क्योंकि वैश्विक स्थिति में पोकिंग है, क्योंकि यह इस तरह काम करता है। glUseProgram एक वैश्विक चर सेट कर रहा है जो glDraw* यह जानने के लिए पढ़ता है कि किस शेडर का उपयोग करना है।

इसलिए, यदि आप यह सुनिश्चित करना चाहते हैं कि कोई विशेष ड्रॉ कॉल किसी विशेष शेडर का उपयोग करता है, तो आपको तुरंत glUseProgram होना चाहिए जो तुरंत पहले शेडर हो। या कम से कम हाल ही में पर्याप्त है कि आप जानते हैं कि आपने इसे कहीं और नहीं बदला है। आम तौर पर, किसी ऑब्जेक्ट के लिए प्रतिपादन इस तरह दिखता है:

  • ऑब्जेक्ट को प्रस्तुत करने के लिए वर्टेक्स विशेषताओं को स्थापित करें।
  • वर्तमान प्रोग्राम सेट करें, और प्रति-ऑब्जेक्ट वर्दी (matrices, आदि) को बदलें।
  • कार्यक्रम के लिए बाध्य बनावट, यदि कोई हो।
  • कार्यक्रम के लिए अन्य राज्य, अगर कोई हो।
  • प्रस्तुत करें।
  • निष्क्रिय

पहला कदम glEnableVertexAttribArray का उपयोग करता है, glBindBuffer, और glVertexAttribPointer जिम्मेदार बताते हैं। ये फ़ंक्शंस, जैसे glUseProgramवैश्विक राज्य सेट करें। ऑब्जेक्ट के साथ प्रस्तुत करने के बाद आपको glDisableVertexAttribArray का उपयोग करना चाहिए, और आपको किसी भी बफर का उपयोग करना चाहिए जो आपने उपयोग किया हो।

+0

विस्तृत स्पष्टीकरण, निकोल के लिए बहुत धन्यवाद। – KomodoDave

+0

ग्रेट प्रतिक्रिया, स्पष्ट और संक्षिप्त। आपका बहुत बहुत धन्यवाद। – rayred