वर्टेक्स ऐरे ऑब्जेक्ट्स क्या हैं?


114

मैं अभी इस ट्यूटोरियल से ओपनजीएल सीखना शुरू कर रहा हूं : http://openglbook.com/the-book/
मुझे अध्याय 2 मिला है, जहां मैं एक त्रिकोण खींचता हूं, और मैं VAOs को छोड़कर सब कुछ समझता हूं (क्या यह संक्षिप्त रूप से ठीक है?)। ट्यूटोरियल में यह कोड है:

glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);

जबकि मैं समझता हूं कि कोड आवश्यक है, मुझे कोई सुराग नहीं है कि यह क्या करता है। हालाँकि, मैं इस बिंदु से पहले कभी भी VaoId का उपयोग नहीं करता (इसे नष्ट करने के अलावा), कोड इसके बिना काम नहीं करता है। मैं यह मान रहा हूं क्योंकि यह बाध्य होना आवश्यक है, लेकिन मुझे नहीं पता कि क्यों। क्या इस सटीक कोड को बस हर OpenGL कार्यक्रम का हिस्सा होना चाहिए? ट्यूटोरियल VAOs के रूप में बताते हैं:

वर्टेक्स एरे ऑब्जेक्ट (या वीएओ) एक ऑब्जेक्ट है जो बताता है कि कैसे वर्टेक्स बफर ऑब्जेक्ट (या वीबीओ) में वर्टेक्स विशेषताओं को संग्रहीत किया जाता है। इसका मतलब यह है कि VAO, शीर्ष डेटा को संग्रहीत करने वाली वास्तविक वस्तु नहीं है, बल्कि वर्टेक्स डेटा का वर्णनकर्ता है। वर्टेक्स विशेषताओं को glVertexAttribPointer फ़ंक्शन और इसकी दो बहन कार्यों glVertexAttribIPointer और glVertexAttribLPointer द्वारा वर्णित किया जा सकता है, जिनमें से सबसे पहले हम नीचे देखेंगे।

मुझे समझ में नहीं आता कि कैसे VAO शीर्ष गुण का वर्णन करता है। मैंने उन्हें किसी भी तरह से वर्णित नहीं किया है। क्या यह glVertexAttribPointer से जानकारी प्राप्त करता है? मुझे लगता है कि यह होना चाहिए। VAO glVertexAttribPointer से जानकारी के लिए बस एक गंतव्य है?

एक साइड नोट पर, क्या ट्यूटोरियल मैं स्वीकार्य है? वहाँ कुछ भी है जो मैं या एक बेहतर ट्यूटोरियल का पालन करने के लिए देखना चाहिए?

जवाबों:


100

"वर्टेक्स एरे ऑब्जेक्ट" आपको ओपन नाम एआरबी उपसमिति द्वारा सिली नामों के लिए लाया गया है।

इसे एक ज्यामिति वस्तु के रूप में सोचें। (पुराने समय के SGI परफॉर्मर प्रोग्रामर के रूप में, मैं उन्हें जियोसेट्स कहता हूं।) उदाहरण चर / ऑब्जेक्ट के सदस्य आपके शीर्ष सूचक, सामान्य पॉइंटर, कलर पॉइंटर, अट्रिब एन पॉइंटर, ...

जब कोई VAO पहले बाध्य होता है, तो आप इन सदस्यों को कॉल करके असाइन करते हैं

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...;
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...;

और इसी तरह। कौन सी विशेषताएँ सक्षम हैं और आपके द्वारा आपूर्ति किए जाने वाले संकेत VAO में संग्रहीत हैं।

उसके बाद जब आप फिर से वीएओ को बांधते हैं, तो वे सभी विशेषताएँ और संकेत भी चालू हो जाते हैं। इसलिए एक glBindVertexArrayकॉल सभी विशेषताओं को सेट करने के लिए आवश्यक सभी कोड के बराबर है। यह अपनी खुद की संरचना या वस्तुओं को बनाने के बिना कार्यों या विधियों के बीच ज्यामिति पास करने के लिए आसान है।

(एक समय सेटअप, एकाधिक उपयोग VAO का उपयोग करने का सबसे आसान तरीका है, लेकिन आप इसे केवल बाइंड करके और अधिक सक्षम / पॉइंटर कॉल करके भी विशेषताओं को बदल सकते हैं। VAOs निरंतर नहीं हैं।)

पैट्रिक के सवालों के जवाब में अधिक जानकारी:

नव निर्मित VAO के लिए डिफ़ॉल्ट यह खाली (AFAIK) है। कोई रेखागणित नहीं, यहां तक ​​कि वर्टेक्स भी नहीं, इसलिए यदि आप इसे खींचने की कोशिश करते हैं, तो आपको ओपनजीएल त्रुटि मिलेगी। यह यथोचित समझदारी है, जैसा कि "फाल्स / NULL / शून्य के लिए सब कुछ इनिशियलाइज़ करें"।

आपको केवल glEnableClientStateचीजों को सेट करने की आवश्यकता है । VAO प्रत्येक पॉइंटर के लिए सक्षम / अक्षम स्थिति को याद करता है।

हाँ VAO स्टोर करेगा glEnableVertexAttribArrayऔर glVertexAttrib। पुराने शीर्ष, सामान्य, रंग, ... सरणियाँ विशेषता सरणियों के समान हैं, शीर्ष == # 0 और इसी तरह।


62
'' वर्टेक्स एरे ऑब्जेक्ट '' को आपके लिए ओपन नेगेटिव एआरबी उपसमिति द्वारा सिली नेम के लिए लाया गया है। '' हां, किसी ऑब्जेक्ट के लिए ऐसा मूर्खतापूर्ण नाम जो वर्टेक्स ऐरे बाइंडिंग को स्टोर करता है ।
निकोल बोलस

2
इसके अलावा, सभी संबंधित हैंglVertexAttribPointer
पैट्रिक

2
जो लोग कोर प्रोफाइल का उपयोग कर रहे हैं, उनके लिए जेनेरिक वर्टेक्स विशेषताओं के उपयोग के बारे में कुछ जानकारी जोड़ें।
Oskar

8
@ निचलोलस एक बेहतर नाम VertexArrayMacroया कुछ इसी तरह का होगा।
बोबोबो

7
@ निचलोल "वर्टेक्स एरे ऑब्जेक्ट" एक भयानक नाम है। यह विशेषताओं के लिए बाध्यकारी डेटा के बारे में है । जैसा कि नाम से ही स्पष्ट है, यह वर्टिस की सरणी के बारे में नहीं है। नाम में बाइंडिंग या विशेषताओं का कोई संदर्भ नहीं है, और चूंकि "वर्टेक्स ऐरे" एक अलग अवधारणा है, यह समझ को और भी कठिन बनाता है। आईएमएचओ, "(वर्टेक्स) एट्रीब्यूट्स बाइंडिंग ऑब्जेक्ट" को समझना आसान है। यहां तक ​​कि ज्योमेट्री ऑब्जेक्ट बेहतर है: मुझे यह पसंद नहीं है, लेकिन कम से कम यह अतिभारित नहीं है।
एकिरोस

8

वर्टेक्स ऐरे ऑब्जेक्ट्स वर्ड प्रोसेसिंग प्रोग्राम और मैक्रो में मैक्रो की तरह हैं। एक अच्छा वर्णन यहाँ पाया गया है

मैक्रो बस याद जब आप फोन इस तरह के सक्रिय इस विशेषता, बाँध कि बफर, आदि के रूप में कार्रवाई तुमने किया था, glBindVertexArray( yourVAOId ), यह बस रिप्ले उन विशेषता सूचक बाइंडिंग और बाइंडिंग बफ़र।

तो आपका अगला कॉल VAO द्वारा जो कुछ भी था, उसका उपयोग करने के लिए है।

VAO के शीर्ष डेटा संग्रहीत नहीं है । नहीं। शीर्ष डेटा को एक शीर्ष बफर या क्लाइंट मेमोरी की एक सरणी में संग्रहीत किया जाता है ।


19
-1: वे मैक्रोज़ की तरह नहीं हैं। अगर वे थे, तो एक नया VAO बंधन को निष्क्रिय नहीं होता शिखर सरणियों, पिछले एक VAO रूप से सक्षम है, जब तक नई VAO "रिकॉर्ड" है आप स्पष्ट रूप से उन सरणियों अक्षम हो जाए। VAO, सभी OpenGL ऑब्जेक्ट्स की तरह , स्टेट को होल्ड करते हैं , कमांड्स को नहीं। कमांड केवल राज्य बदलते हैं , लेकिन ऑब्जेक्ट डिफ़ॉल्ट राज्य सेट के साथ आते हैं। यही कारण है कि एक नव निर्मित VAO को हमेशा सभी विशेषताओं को अक्षम करना होगा ।
निकोल बोलस

6

मैं हमेशा VAO के बारे में OpenGL द्वारा उपयोग किए जाने वाले डेटा बफ़र्स की एक सरणी के रूप में सोचता हूं। आधुनिक OpenGL का उपयोग करके आप एक VAO और वर्टेक्स बफर ऑब्जेक्ट बनाएंगे।

यहां छवि विवरण दर्ज करें

//vaoB is a buffer
glGenVertexArrays(1, vaoB); //creates one VAO
glBindVertexArray(vao.get(0));
glGenBuffers(vbo.length, vbo, 0); //vbo is a buffer
glBindVertexArray(vao.get(1));
glGenBuffers(vbo1.length, vbo1, 0); //vbo1 is a buffer
glBindVertexArray(vao.get(2));
glGenBuffers(vbo2.length, vbo2, 0); //vbo2 is a buffer

अगला कदम डेटा को एक बफर में बाँधना है:

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER,vertBuf.limit()*4, vertBuf, GL_STATIC_DRAW); //vertf buf is a floatbuffer of vertices

इस बिंदु पर OpenGL Sees:

यहां छवि विवरण दर्ज करें

अब हम GlGLertexAttribPointer का उपयोग OpenGL को बताने के लिए कर सकते हैं कि बफर में डेटा क्या दर्शाता है:

glBindBuffer(GL_ARRAY_BUFFER, 0); //bind VBO at 0
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); //each vertex has 3 components of size GL_FLOAT with 0 stride (space) between them and the first component starts at 0 (start of data)

यहां छवि विवरण दर्ज करें

OpenGL के पास अब बफर में डेटा है और जानता है कि डेटा को वर्टिकल में कैसे व्यवस्थित किया जाता है। एक ही प्रक्रिया को बनावट निर्देशांक आदि के लिए लागू किया जा सकता है लेकिन बनावट निर्देशांक के लिए दो मूल्य होंगे।

glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER,coordBuf.limit()*4, coordBuf, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);

आगे आप बनावट को बांध सकते हैं और सरणियों को आकर्षित कर सकते हैं, आप एक वर्ट और फ्रैग शेडर बनाना चाहेंगे, इसे एक प्रोग्राम में संकलित और संलग्न कर सकते हैं (यहां शामिल नहीं हैं)।

glActiveTexture(textureID); //bind our texture
glBindTexture(GL_TEXTURE_2D, textureID);
glDrawArrays(GL_TRIANGLES,0,6); //in this case 6 indices are used for two triangles forming a square

5

VAO एक ऐसी वस्तु है जो OpenGL पाइपलाइन के वर्टेक्स फ़िंच चरण का प्रतिनिधित्व करती है और इसका उपयोग वर्टेक्स शेडर में इनपुट की आपूर्ति करने के लिए किया जाता है।

आप इस तरह से वर्टेक्स ऐरे ऑब्जेक्ट बना सकते हैं

GLuint vao;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);

पहले एक सरल उदाहरण देते हैं। एक shader कोड में इस तरह के इनपुट पैरामीटर पर विचार करें

layout (location = 0) in vec4 offset; // input vertex attribute

इस विशेषता को भरने के लिए हम इसका उपयोग कर सकते हैं

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0

यद्यपि वर्टेक्स ऐरे ऑब्जेक्ट आपके लिए इन स्थैतिक विशेषता मूल्यों को संग्रहीत करता है, लेकिन यह बहुत अधिक कर सकता है।

वर्टेक्स ऐरे ऑब्जेक्ट बनाने के बाद हम इसके राज्य में भरना शुरू कर सकते हैं। हम OpenGL को एक बफर ऑब्जेक्ट में संग्रहीत डेटा का उपयोग करके इसे स्वचालित रूप से भरने के लिए कहेंगे जो हम आपूर्ति करते हैं। प्रत्येक वर्टेक्स विशेषता को एक बफर से कई वर्टेक्स बफर बाइंडिंग से डेटा प्राप्त करने के लिए मिलता है। इस अंत के लिए हम उपयोग करते हैं glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex)। इसके अलावा, हम glVertexArrayVertexBuffer()एक बफर को बाइंडरों के शीर्ष पर बाँधने के लिए फ़ंक्शन का उपयोग करते हैं । हम glVertexArrayAttribFormat()डेटा के लेआउट और प्रारूप का वर्णन करने के लिए फ़ंक्शन का उपयोग करते हैं , और अंत में हम कॉल करके विशेषता के स्वत: भरने को सक्षम करते हैं glEnableVertexAttribArray()

जब एक शीर्ष विशेषता सक्षम किया गया है, ओपन शीर्ष प्रारूप और स्थान की जानकारी आप के साथ प्रदान की है, उसके आधार शेडर करने के लिए डेटा फीड होगा glVertexArrayVertexBuffer()और glVertexArrayAttribFormat()। जब विशेषता को अक्षम कर दिया जाता है, तो वर्टेक्स शेडर को आपके द्वारा प्रदान की जाने वाली स्थैतिक जानकारी प्रदान की जाएगी glVertexAttrib*()

// First, bind a vertex buffer to the VAO
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4));

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic
// vertex fetching for the specified attribute
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);

glEnableVertexArrayAttrib(vao, 0);

और एक shader में कोड

layout (location = 0) in vec4 position;

आखिरकार आपको कॉल करने की आवश्यकता है glDeleteVertexArrays(1, &vao)


इसे बेहतर समझने के लिए आप OpenGL SuperBible को पढ़ सकते हैं ।


3
यह देखने के लिए अच्छा है कि लोग डीएसए-शैली ओपनगेल के उपयोग को बढ़ावा देते हैं।
निकोल बोलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.