2012-01-06 42 views
9

मैं कुछ ट्यूटोरियल का पालन करके और कुछ स्वयं के कुछ प्रयोगों को कोड करके ओपनजीएल सीख रहा हूं। लेकिन एक बात है जो मैं वास्तव में समझ में नहीं आता जो मुझे जारी रखने से रोकता है। मैं अब कुछ घंटों के लिए गुगल रहा हूं और अभी तक मेरे प्रश्न का उत्तर नहीं मिला है।ओपनगलएस 2.0 वर्टिस, रंग और बनावट के लिए अलग-अलग बफर

मुझे प्रत्येक अलग-अलग कशेरुक के लिए प्रत्येक अलग रंग मान और बनावट समन्वय कहां निर्दिष्ट करना चाहिए? क्या उन गुणों को हमेशा वर्टेक्स पदों के समान सारणी (संरचना) में सूचीबद्ध किया जाना चाहिए? इस तरह:

const Vertex Vertices[] = { 
    // Front 
    {{1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, 
    {{1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, 
    {{-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, 
    {{-1, -1, 0}, {0, 0, 0, 1}, {0, 0}}, 

    ... 

या अलग-अलग सरणी में रंग मान और बनावट निर्देशांक डालने का कोई तरीका है? लेकिन फिर सवाल उठता है: मैं विभिन्न arrays के साथ glDrawElements कैसे कॉल करूं?

यदि आप सोच रहे हैं कि मैं इन मानों को अलग क्यों करना चाहता हूं: मैं वर्तमान में ओबीजे-सी में अपना स्वयं का .obj पार्सर बना रहा हूं और मैं सोच रहा था: क्या होगा यदि आप बनावट के बिना मॉडल लोड करते हैं और केवल दिखाना चाहते हैं वस्तु पर एक रंग? या: क्या होगा यदि आप मॉडल को केवल एक बनावट के साथ लोड करना चाहते हैं लेकिन प्रति कशेरुक अलग रंग नहीं है? और: बहुत अधिक डेटा के साथ वेरटेक्स संरचना को फूलाते हुए रंग मान और बनावट समन्वय नहीं डाल रहा है।

उत्तर

21

वास्तव में यह कशेरुक डेटा को स्थिति, रंग, आदि कई arrays/बफर का उपयोग कर।

पिछली बार जब मैं ईएस 2.0 के संपर्क में आया तो वेबजीएल के संदर्भ में था (जिसमें थोड़ा अलग नमूना है लेकिन अंत में ईएस 2.0 पर आधारित है)।

क्या मूल रूप से किया जाता है

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), positions, GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), colors, GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

... 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort), indices, GL_STATIC_DRAW); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
पदों और रंग नाव शिखर डेटा और इस मामले में अहस्ताक्षरित शॉर्ट्स के रूप में सूचकांक युक्त सूचकांक युक्त सरणियों होने के साथ

का उपयोग कर अलग बफ़र्स के लिए डेटा लिख ​​रहा है।

इस डेटा प्रस्तुत करना के लिए, आपको बफ़र्स उपयोग करें और अपनी शेडर की ओर इशारा विशेषता चाहते हैं:

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
glVertexAttribPointer(vertexPositionAttribute, 3, GL_FLOAT, false, 0, 0); 

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
glVertexAttribPointer(vertexColorAttribute, 4, GL_FLOAT, false, 0, 0); 

अंत में सूचकांक बफर बाँध:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 

और प्रस्तुत करना:

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0); 

विशेषताएँ प्राप्त करने के लिए:

glUseProgram(shaderProgram); 

vertexPositionAttribute= glGetAttribLocation(shaderProgram, "vertexPosition"); 
glEnableVertexAttribArray(vertexPositionAttribute); 

vertexColorAttribute = glGetAttribLocation(shaderProgram, "vertexColor"); 
glEnableVertexAttribArray(vertexColorAttribute); 

... 

आप (फिक्स्ड समारोह का उपयोग करके) कस्टम shaders नहीं है, तो आप के बजाय

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
glVertexPointer(3, GL_FLOAT, false, 0, 0); 

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
glColorPointer(4, GL_FLOAT, false, 0, 0); 

उपयोग करने में सक्षम हो सकता है। मैं इसके खिलाफ सलाह दूंगा, हालांकि, यह पुराना है (अगर ईएस 2.0 में उपलब्ध है)। आप अभी भी इसका उपयोग करना चाहते हैं, तो आप पूरे बफर व्यापार पूरी तरह छोड़ सकते हैं और

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, indices); 

मुझे आशा है कि वह भी भ्रमित नहीं था और थोड़ा में मदद करता है के साथ

glVertexPointer(3, GL_FLOAT, false, 0, positions); 
glColorPointer(4, GL_FLOAT, false, 0, colors); 

उपयोग कर सकते हैं। आगे पढ़ने के लिए, हालांकि ओपनजीएल पर लक्षित, मैं Nehe tutorials का सुझाव दूंगा।

+0

क्रिस्टल स्पष्ट! ;) – polyclick

0

आप उन्हें सब-बफर में अलग कर सकते हैं लेकिन यदि आप उनका उपयोग करते हैं तो आपको उन्हें सभी कोष्ठकों के लिए रखना होगा और यदि आप इंडेक्स-बफर का उपयोग करते हैं तो आपको सभी के लिए एक इंडेक्स-बफर का उपयोग करना होगा (स्थिति, रंग, टेक्साकोर्ड, आदि)। यहाँ मेरी कोड से कुछ अंश इस प्रकार हैं:

glBufferSubData(GL_ARRAY_BUFFER, mVertexOffset, numberOfVertsToStore * mVertexBlockSize, vertices); 
glBufferSubData(GL_ARRAY_BUFFER, mNormalOffset, numberOfVertsToStore * mNormalBlockSize, normals); 
glBufferSubData(GL_ARRAY_BUFFER, mColorOffset, numberOfVertsToStore * mColorBlockSize, colors); 
glBufferSubData(GL_ARRAY_BUFFER, mTexCoordOffset, numberOfVertsToStore * mTexCoordBlockSize, texCoords); 

और इस के साथ उपयोग के साथ भरने

glBindBuffer(GL_ARRAY_BUFFER, mId); 
glBufferData(GL_ARRAY_BUFFER, 
       mMaxNumberOfVertices * (mVertexBlockSize + mNormalBlockSize + mColorBlockSize + mTexCoordBlockSize), 
       0, 
       mDrawMode); 

साथ आवंटन (मुझे नहीं लगता कि लगातार स्विचन clientStates सबसे अच्छा अभ्यास है, हालांकि)

void Vbo::draw(GLenum primMode) 
{ 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glVertexPointer(mVertexComponents, GL_FLOAT, 0, (void*)mVertexOffset); 

    if(mNormalBlockSize){ 
    glEnableClientState(GL_NORMAL_ARRAY); 
    glNormalPointer(GL_FLOAT, 0, (void*)mNormalOffset); 
    } 
    if(mColorBlockSize){ 
    glEnableClientState(GL_COLOR_ARRAY); 
    glColorPointer(mColorComponents, GL_FLOAT, 0, (void*)mColorOffset); 
    } 
    if(mTexCoordBlockSize){ 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    glTexCoordPointer(mTexCoordComponents, GL_FLOAT, 0, (void*)mTexCoordOffset); 
    } 

    if (mAttachedIndexBuffer) 
    { 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mAttachedIndexBuffer); 
    glDrawElements(primMode, 
        mAttachedIndexBuffer->getNumberOfStoredIndices(), 
        mAttachedIndexBuffer->getDataType(), 
        0); 
    } 
    else 
    { 
    glDrawArrays(primMode, 0, mNumberOfStoredVertices); 
    } 

    if(mTexCoordBlockSize) 
    { 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    } 
    if(mColorBlockSize) 
    { 
    glDisableClientState(GL_COLOR_ARRAY); 
    } 
    if(mNormalBlockSize) 
    { 
    glDisableClientState(GL_NORMAL_ARRAY); 
    } 
    glDisableClientState(GL_VERTEX_ARRAY); 
}  
+1

यदि आप पूरी तरह से अलग-अलग बफर में अलग-अलग विशेषताओं को स्टोर कर सकते हैं, तो वास्तव में प्रश्न का उत्तर नहीं देते हैं। –

+0

मेरा बुरा। मैंने अभी नहीं सोचा था कि उप-बफर और पूरी तरह से अलग-अलग बफर का उपयोग करने के बीच एक महत्वपूर्ण अंतर था, क्योंकि उन्हें एक साथ आवंटित किया जाएगा, एक साथ हटा दिया जाएगा और यदि वे एक ही ऑब्जेक्ट के लिए अलग-अलग डेटा रखते हैं तो हमेशा एक साथ उपयोग किया जाता है। – PeterT

+0

दरअसल सच है, लेकिन फिर भी उसने जवाब देने के लिए एक प्रश्न पूछा। –

2

आप निश्चित रूप से अलग-अलग बफर में अपना डेटा प्राप्त कर सकते हैं। ध्यान रखें कि यह glVertexAttribPointer कॉल है जो एक विशेषता का स्रोत निर्धारित करता है। इसलिए किसी विशेषता के लिए एक अलग बफर का उपयोग करने के लिए, glVertexAttribPointer पर कॉल करने से पहले बस एक अलग GL_ARRAY_BUFFER बांधें।

:

glBindBuffer(GL_ARRAY_BUFFER, positionBuffer); 
glVertexAttribPointer(0, ...); 
glEnableVertexAttribArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
glVertexAttribPointer(1, ...); 
glEnableVertexAttribArray(1); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 
glDrawElements(...); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 

VBOs (जो मुझे यकीन है कि ES 2.0 में संभव है नहीं कर रहा हूँ) का उपयोग नहीं करते हैं, तो सिर्फ glVertexAttribPointer प्रत्येक विशेषता के लिए एक अलग सरणी के साथ फोन: glDrawElements यह से कोई लेना देना नहीं है

glVertexAttribPointer(0, ..., positionArray); 
glEnableVertexAttribArray(0); 
glVertexAttribPointer(1, ..., colorArray); 
glEnableVertexAttribArray(1); 

glDrawElements(..., indexArray); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 

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

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