2013-05-04 19 views
8

mam problemu z moją tablicę wierzchołków wskazał prawidłowo:OpenGL 3/4 glVertexAttribPointer krok i offset pomyłka

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); 

Nie rozumiem, w jaki sposób krok i offset pracy. Jaki jest prawidłowy sposób korzystania z glVertexAttribPointer() w mojej sytuacji?

Odpowiedz

21

Stride i offset podano w bajtach. Używasz przeplatanej tablicy wierzchołków z pozycją i kolorem zarówno jako 4 spławiki. Aby przejść od pierwszego elementu do konkretnej tablicy atrybutów do następnego, odległość wynosi 8, więc krok powinien wynosić 8 * sizeof (GLfloat). Przesunięcie jest pozycją bajtu pierwszego elementu każdej tablicy atrybutów w buforze, więc w twoim przykładzie dla pozycji jest 0, a dla koloru jest to 4 * sizeof (GLfloat)

+0

jakie powinny być moje dwie wartości glVertexAttribPointer? – user2350858

+0

@ user2350858: Tak jak już napisałem w odpowiedzi: krok to 8 * sizeof (GLfloat) (tak zazwyczaj 32) i offset 0 dla pozycji i 4 * sizeof (GLfloat) dla koloru (jak już to robisz) – derhass

15

Ponieważ glVertexAttribPointer często sprawia kłopoty, Próbuję to wyjaśnić tutaj.

Wzór do obliczenia POS rozpoczęcia atrybutu i-w atrybutach macierzy jest:

startPos(i) = offset + i * stride (Z derhass' another answer)

i wyjaśnione w poniższym wykresie: tightly packed arrtibute array


Jeśli potrzebujesz przykładowego kodu, kontynuuj czytanie.

Od Formatting VBO Data wiemy, że możemy zarządzać naszymi danymi werteksów w trzech formatach. Zrób przykład rysując trójkąt kolorem vert i kolor tekstury mieszane, oto sposób na przygotowanie vert danych atrybutu:


# way1 Każdy atrybut do VBO.

tego formatu jak: (xyzxyz ...) (rgbrgb ...) (STST ....), a my możemy pozwolić zarówno sride = 0 i offset = 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]); 
} 

# way2: Każdy atrybut jest sekwencyjny, podzielony na pojedyncze VBO.

Format ten jest następujący: (xyzxyzxyz ... rgbrgb ... ststst ...), możemy pozwolić kroku = 0, ale należy podać offset.

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: atrybut przeplotem w jednym VBO

tym formacie jest jak: (xyzrgbstxyzrgbst ...), musimy ręcznie określić przesunięcie i kroku.

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); 
} 

Dziękuję za odpowiedź derhassa.

+0

Wow, byłem próbując otoczyć mózg różnicami 3 metod przez większą część dnia (przeważnie przeplatanie się z innymi i jak prawidłowo używać przesunięcia), wtedy zobaczyłem to obok siebie i wszystko stało się jasne. Dzięki. ;) Każdy pomysł, który zwykle jest szybszy? –