2013-05-04 34 views
8

benim köşe dizisi alma sorun yaşıyorum düzgün çekti:OpenGL 3/4 glVertexAttribPointer adım ve ofset yanlış hesap

const float vertices[] = { 
/* position */ 0.75f, 0.75f, 0.0f, 1.0f, /* color */ 1.0f, 0.0f, 0.0f, 1.0f, 
/* position */ 0.75f, -0.75f, 0.0f, 1.0f, /* color */ 0.0f, 1.0f, 0.0f, 1.0f, 
/* position */ -0.75f, -0.75f, 0.0f, 1.0f, /* color */ 0.0f, 0.0f, 1.0f, 1.0f, }; 

... 

glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 
glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)16); 

glDrawArrays(GL_TRIANGLES, 0, 3); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 

anlamıyorum nasıl adım ve ofset çalışır. Durumumda glVertexAttribPointer()'u kullanmanın doğru yolu nedir?

cevap

21

Adım ve ofset, bayt cinsinden belirtilmiştir. Hem 4 şamandıra hem de konumu ve rengi olan bir araya getirilmiş köşe dizisi dizisi kullanıyorsunuz. Belirli bir öznitelik dizisindeki bir ikinci elemandan birinciye geçmek için, 8 şaftın mesafesi vardır, bu nedenle 8 * boyut (GLfloat) olmalıdır. Ofset, tampondaki her bir öznitelik dizisinin ilk öğesinin bayt konumudır; bu nedenle, örnek için konum 0'dır ve renk için, 4 * boyutundadır (GLfloat)

+0

İki glVertexAttribPointer adım ve ofset değerlerim ne olmalıdır? – user2350858

+0

@ user2350858: Cevapta yazdığım gibi: adım 8 * boyut (GLfloat) (yani, genellikle 32) ve konum için ofset 0 ve (zaten yaptığınız gibi) renk için 4 * sizeof (GLfloat) – derhass

15

GlVertexAttribPointer sık ​​sık sıkıntı yarattığından, Burada daha fazla açıklamaya çalışıyorum.

özellikler dizisindeki i-inci öznitelik başlangıç ​​konumunu hesaplamak için formül şöyledir:

(derhass' another answer elde edilmiş) ve aşağıdaki grafikte açıklandığı

startPos(i) = offset + i * stride: tightly packed arrtibute array


Kod örneğine ihtiyacınız varsa, okumaya devam edin.

Formatting VBO Data'dan itibaren, vertex verimizi üç biçimde yönetebileceğimizi biliyoruz. Her bir VBO bağlıyor


# way1: vert renk ve karışık doku rengi ile, bir üçgen çizimi bir örneğini olun burada vert nitelik verilerini hazırlamak için bir yoldur.

gibi bu formatı: (xyzxyz ...) (rgbrgb ...) (StSt ....) ve biz de sride = 0 izin verebilir ve = 0.

void prepareVertData_moreVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 
    GLfloat vertPos[] = { 
     -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, // positon 
    }; 
    GLfloat vertColor[] = { 
     1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // color 
    }; 
    GLfloat vertTextCoord[] = { 
     0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f  // texture coordinate 
    }; 

    GLuint VBOId[3]; 

    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 
    glGenBuffers(3, VBOId); 
    // specify position attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[0]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertPos), vertPos, GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[1]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertColor), vertColor, GL_STATIC_DRAW); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate attribute 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId[2]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertTextCoord), vertTextCoord, GL_STATIC_DRAW); 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId[0]); 
    VBOIdVec.push_back(VBOId[1]); 
    VBOIdVec.push_back(VBOId[2]); 
} 
ofset

# way2: Her bir öznitelik, tek bir VBO'da toplu işlenir.

bu biçim gibidir: (xyzxyzxyz ... rgbrgb ... ststst ...), stride = 0'a izin verebiliriz, ancak ofset belirtilmelidir.

void prepareVertData_seqBatchVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 

    GLfloat vertices[] = { 
    -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, // position 
    1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // color 
    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f  // texture coordinate 
    }; 

    GLuint VBOId; 
    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 

    glGenBuffers(1, &VBOId); 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    // specifiy position attribute 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); // stride can aslo be 3 * sizeof(GL_FLOAT) 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(9 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(18 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId); 
} 

# way3: Tek VBO

bu biçimde Aralıklı niteliği gibidir: (xyzrgbstxyzrgbst ...), elle ofset ve adım belirtmek gerekir.

void prepareVertData_interleavedBatchVBO(GLuint& VAOId, std::vector<GLuint>& VBOIdVec) 
{ 
    // interleaved data 
    GLfloat vertices[] = { 
     -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0 
     0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 1 
     0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // 2 
    }; 

    GLuint VBOId; 
    glGenVertexArrays(1, &VAOId); 
    glBindVertexArray(VAOId); 
    glGenBuffers(1, &VBOId); 
    glBindBuffer(GL_ARRAY_BUFFER, VBOId); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    // specify position attribute 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,8 * sizeof(GL_FLOAT), (GLvoid*)0); 
    glEnableVertexAttribArray(0); 
    // specify color attribute 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 
     8 * sizeof(GL_FLOAT),(GLvoid*)(3 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(1); 
    // specify texture coordinate 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 
     8 * sizeof(GL_FLOAT), (GLvoid*)(6 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    VBOIdVec.push_back(VBOId); 
} 

Ve derhass'ın cevabı için teşekkürler.

+0

Wow, beynimi bir günün en iyi kısmı için 3 yöntemin farklılıkları etrafında sarmalamaya çalışıyorum (çoğu zaman diğerlerine karşı serpiştirmek ve doğru ofsetin nasıl kullanılacağını), sonra bunu yan yana gördüm ve her şey netleşti. Teşekkürler. ;) Genellikle daha hızlı olan herhangi bir fikir? –