2016-10-07 10 views
5

मुझे समझ नहीं आता क्या उद्देश्य ओपन में बाध्यकारी अंक (जैसे GL_ARRAY_BUFFER) की है। मेरी समझ glGenBuffers() करने के लिए एक शीर्ष बफर GPU स्मृति भीतर कहीं स्थित वस्तु के लिए सूचक का एक तरह बनाता है।ओपनजीएल में बाध्यकारी बिंदुओं का उद्देश्य?

तो:

glGenBuffers(1, &bufferID) 

का मतलब है अब मैं एक संभाल, bufferID, ग्राफिक्स कार्ड पर 1 शिखर वस्तु किया है। अब मुझे पता है अगले कदम के एक बाध्यकारी बात करने के लिए बाध्य करने के लिए bufferID

glBindBuffer(GL_ARRAY_BUFFER, bufferID) 

ताकि मैं उस बंधन बिंदु तो जैसे glBufferData() समारोह का उपयोग कर नीचे डेटा भेजने के लिए उपयोग कर सकते हैं होगा:

glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW) 

लेकिन क्यों क्या मैं सिर्फ बफरिड का उपयोग निर्दिष्ट नहीं कर सकता हूं जहां मैं इसके बजाय डेटा भेजना चाहता हूं? कुछ की तरह:

glBufferData(bufferID, sizeof(data), data, GL_STATIC_DRAW) 

फिर जब एक ड्रॉ समारोह मैं भी बस रखा, जिसमें कभी आईडी जो भी VBO मैं ड्रॉ समारोह आकर्षित करने के लिए चाहते हैं बुला। की तरह कुछ:

glDrawArrays(bufferID, GL_TRIANGLES, 0, 3) 

क्यों हम glBindBuffers साथ अविवेक की अतिरिक्त कदम की जरूरत है?

+0

"* का मतलब है कि अब मेरे पास एक हैंडल, बफरिड, 1 वर्टेक्स ऑब्जेक्ट * * एक * बफर ऑब्जेक्ट * है। "Vertex ऑब्जेक्ट" जैसी कोई चीज़ नहीं है। –

+1

"मैं बस निर्दिष्ट करने के लिए बफर आईडी का उपयोग क्यों नहीं कर सकता हूं, जहां मैं इसके बजाय डेटा भेजना चाहता हूं?" ... ['ARB_direct_state_access'] (https://www.opengl.org/wiki/Direct_State_Access)? – genpfault

उत्तर

9

ओपन का उपयोग करता है दो बातों के लिए बाध्यकारी अंक आपत्ति: एक वस्तु एक प्रतिपादन की प्रक्रिया के हिस्से के रूप में प्रयोग की जाने वाली नामित करने के लिए, और वस्तु को संशोधित करने में सक्षम हो।

क्यों यह उनके पूर्व के लिए उपयोग करता है सरल है: ओपन रेंडर करने के लिए सक्षम होने के लिए वस्तुओं का एक बहुत आवश्यकता है।

अपने बेहद साधारण उदाहरण पर विचार करें:

glDrawArrays(bufferID, GL_TRIANGLES, 0, 3) 

एपीआई मुझे अलग शिखर गुण अलग बफ़र्स से आए हैं नहीं करता है। निश्चित रूप से, आप glDrawArrays(GLint count, GLuint *object_array, ...) का प्रस्ताव दे सकते हैं। लेकिन आप किसी विशेष बफर ऑब्जेक्ट को किसी विशेष वर्टेक्स विशेषता से कैसे कनेक्ट करते हैं? या आपके पास बफर 0 से 2 विशेषताएं और बफर 1 से तीसरी विशेषता कैसे है? वे चीजें हैं जो मैं वर्तमान एपीआई के साथ अभी कर सकता हूं। लेकिन आपका प्रस्तावित व्यक्ति इसे संभाल नहीं सकता है। कार्यक्रम/पाइपलाइन वस्तुओं, बनावट वस्तुओं, UBOs, SSBOs, बदलने प्रतिक्रिया वस्तुओं, क्वेरी वस्तुओं, आदि में निर्दिष्ट की जरूरत की वस्तुओं के सभी के बाद:

और यहां तक ​​कि एक तरफ कई अन्य वस्तुओं आप रेंडर करने के लिए की जरूरत है डाल रहा है एक ही आदेश मौलिक रूप से अनावश्यक होगा (और यह प्रदर्शन लागत को छोड़ देता है)।

और हर बार एपीआई को एक नई तरह की वस्तु जोड़ने की आवश्यकता होगी, तो आपको glDraw* फ़ंक्शंस के नए बदलाव जोड़ना होगा। और अभी, over a dozen such functions हैं। आपके रास्ते ने हमें सैकड़ों दिया होगा।

तो इसके बजाय, ओपनजीएल आपके लिए कहने के तरीकों को परिभाषित करता है "अगली बार जब मैं प्रस्तुत करता हूं, तो इस प्रक्रिया का उपयोग इस प्रक्रिया के लिए करें।" उपयोग के लिए एक वस्तु को बाध्यकारी करना यही है।


लेकिन मैं सिर्फ bufferID specifiy करने के लिए उपयोग नहीं कर सकता है, जहां मैं बजाय डेटा भेजने के लिए करना चाहते हैं?

इस वस्तु संशोधित के प्रयोजन के लिए एक वस्तु बंधन, नहीं कह रही है कि यह उपयोग किया जाएगा के बारे में है। वह है ... एक अलग मामला।

स्पष्ट उत्तर यह है, "आप ऐसा नहीं कर सकते क्योंकि ओपनजीएल एपीआई (4.5 तक) में ऐसा करने के लिए कोई फ़ंक्शन नहीं है।" लेकिन मुझे संदेह है कि सवाल वास्तव में क्यों है ओपनजीएल में ऐसे एपीआई नहीं हैं (4.5 तक, जहां glNamedBufferStorage और ऐसे अस्तित्व में हैं)।

दरअसल, तथ्य यह है कि 4.5 में ऐसे कार्य हैं, यह साबित करता है कि तकनीकी प्री-4.5 ओपनजीएल के बाइंड-ऑब्जेक्ट-टू-संशोधित API के कारण नहीं है। यह वास्तव में एक "निर्णय" था जो 1.0 से ओपनजीएल एपीआई के विकास के बारे में आया था, कम से कम प्रतिरोध के मार्ग का पालन करने के लिए धन्यवाद। बार-बार।

दरअसल, ओपनजीएल द्वारा किए गए हर बुरे निर्णय के बारे में सिर्फ एपीआई में कम से कम प्रतिरोध का मार्ग लेने के लिए पता लगाया जा सकता है। लेकिन मैं पीछे हटा।

ओपनजीएल 1.0 में, केवल एक ही प्रकार की वस्तु थी: प्रदर्शन सूची ऑब्जेक्ट्स। इसका मतलब है कि भी बनावट वस्तुओं में संग्रहित नहीं थे। इसलिए हर बार जब आप बनावट स्विच करते हैं, तो आपको पूरे बनावट को glTexImage*D के साथ फिर से निर्दिष्ट करना होगा। इसका मतलब है कि इसे फिर से अपलोड करना। अब, आप एक बनावट सूची में प्रत्येक बनावट की सृजन को लपेट सकते हैं (और लोगों ने), जिसने आपको उस प्रदर्शन सूची को निष्पादित करके बनावट स्विच करने की अनुमति दी। और उम्मीद है कि चालक को एहसास होगा कि आप ऐसा कर रहे थे और इसके बजाय वीडियो मेमोरी आवंटित और आगे उचित रूप से।

तो जब 1.1 आसपास आया, ओपनजीएल एआरबी को एहसास हुआ कि दिमागी झुकाव कितना मूर्ख था। इसलिए उन्होंने बनावट वस्तुओं को बनाया, जो एक बनावट के स्मृति भंडारण और भीतर के विभिन्न राज्यों को समाहित करते हैं। जब आप बनावट का उपयोग करना चाहते थे, तो आप इसे बाध्य करते थे। लेकिन एक झगड़ा था। अर्थात्, कैसे बदलें।

देखें, 1.0 में glTexImage*D, glTexParamter और इसी तरह के मौजूदा कार्यों का एक समूह था। ये बनावट की स्थिति को संशोधित करते हैं। अब, एआरबी ने नए कार्यों को जोड़ा होगा जो एक ही काम करते हैं लेकिन बनावट वस्तुओं को पैरामीटर के रूप में लेते हैं।

लेकिन इसका मतलब यह होगा कि सभी ओपनजीएल उपयोगकर्ताओं को 2 शिविरों में विभाजित किया जाएगा: जो बनावट वस्तुओं का उपयोग करते थे और जो नहीं करते थे। इसका मतलब यह था कि, यदि आप बनावट वस्तुओं का उपयोग करना चाहते हैं, तो आपको को अपने मौजूदा कोड के को फिर से लिखना होगा जो संशोधित बनावट है। यदि आपके पास कुछ फ़ंक्शन था जिसने वर्तमान बनावट पर glTexParameter कॉल का एक गुच्छा बनाया है, तो आपको नए बनावट ऑब्जेक्ट फ़ंक्शन को कॉल करने के लिए उस फ़ंक्शन को बदलना होगा। लेकिन आप भी को अपने फ़ंक्शन को बदलना चाहते हैं जो इसे कॉल करता है ताकि वह पैरामीटर के रूप में, बनावट बनावट बना सके।

और यदि वह फ़ंक्शन आपके साथ नहीं था (क्योंकि यह उस लाइब्रेरी का हिस्सा था जिसका आप उपयोग कर रहे थे), तो आप भी नहीं कर पाए।

तो एआरबी ने उन पुराने कार्यों को चारों ओर रखने का फैसला किया और बस इस पर निर्भर करता है कि एक बनावट संदर्भ के लिए बाध्य थी या नहीं। यदि कोई बाध्य था, तो glTexParameter/आदि संदर्भ के सामान्य बनावट की बजाय बाध्य बनावट को संशोधित करेगा।

यह एक निर्णय स्थापित the general paradigm shared by almost all OpenGL objects

ARB_vertex_buffer_object इसी कारण से इस प्रतिमान का उपयोग करता है। ध्यान दें कि विभिन्न gl*Pointer फ़ंक्शंस (glVertexAttribPointer और जैसे) बफर के संबंध में कैसे काम करते हैं। आपको GL_ARRAY_BUFFER पर एक बफर बांधना होगा, फिर एक विशेषता सरणी सेट अप करने के लिए उन कार्यों में से एक को कॉल करें। जब एक बफर उस स्लॉट से बंधे होते हैं, तो फ़ंक्शन उस पर उठाएगा और पॉइंटर को ऑफ़सेट के रूप में बफर में रखेगा जो उस समय *Pointer फ़ंक्शन कहलाता था।

क्यों? इसी कारण से: संगतता में आसानी (या आलस्य को बढ़ावा देने के लिए, आप इसे कैसे देखना चाहते हैं) के आधार पर। ATI_vertex_array_object को gl*Pointer फ़ंक्शंस में नए एनालॉग बनाना था। जबकि ARB_vertex_buffer_object बस मौजूदा एंट्री पॉइंट्स से बंद हो गया है।

उपयोगकर्ताओं को glVertexPointer से glVertexBufferOffset या कुछ अन्य फ़ंक्शन का उपयोग करने से बदलने की आवश्यकता नहीं थी। उन्हें केवल एक कार्य को बुलाए जाने से पहले एक बफर बांधना था जो चरम जानकारी स्थापित करता था (और निश्चित रूप से पॉइंटर्स को बाइट ऑफसेट में बदल देता है)।

इसका यह भी अर्थ है कि उन्हें बफर ऑब्जेक्ट्स से आने वाले सूचकांक के साथ प्रतिपादन के लिए glDrawElementsWithBuffer-प्रकार का कार्य जोड़ने की आवश्यकता नहीं थी।

तो यह अल्प अवधि में एक बुरा विचार नहीं था। लेकिन अधिकांश अल्पकालिक निर्णय लेने के साथ, यह समय के साथ कम उचित होने लगता है।

बेशक, यदि आपके पास जीएल 4.5/ARB_direct_state_access तक पहुंच है, तो आप चीजों को मूल रूप से करने के तरीके से कर सकते हैं।

+0

इस ऐतिहासिक प्रक्रिया आधारित स्पष्टीकरण के लिए धन्यवाद। ओपनजीएल के साथ शुरू होने पर सभी अत्यधिक आर्केन, वर्बोज़, जटिल बकवास को पचाना पड़ता है, अंत में कुछ तर्कसंगत समझाया जाता है जब अंत में कुछ समझ में आता है। यह कोड को देखने के लिए कोई सुंदर नहीं बनाता है, लेकिन यह एपीआई को नेविगेट करने की मेरी समझ में सहायता करता है। – user69513

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