2013-05-04 29 views
8

Tôi gặp một vấn đề nhận được mảng đỉnh của tôi chỉ vào đúng:OpenGL 3/4 glVertexAttribPointer sải chân và bù đắp tính toán sai lầm

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

Tôi không hiểu làm thế nào sải chân và làm việc bù đắp. Cách chính xác để sử dụng glVertexAttribPointer() trong trường hợp của tôi là gì?

Trả lời

21

Dọc và bù được xác định theo byte. Bạn đang sử dụng một mảng đỉnh xen kẽ với vị trí và màu sắc là 4 phao. Để có được từ phần tử thứ i trong một mảng thuộc tính cụ thể tới phần tử tiếp theo, có khoảng cách là 8 phao, vì vậy sải chân nên là 8 * sizeof (GLfloat). Phần bù là vị trí byte của phần tử đầu tiên của mỗi mảng thuộc tính trong bộ đệm, vì vậy trong ví dụ của bạn cho vị trí là 0 và màu sắc là 4 * sizeof (GLfloat)

+0

hai giá trị độ lệch và giá trị lệch của glVertexAttribPointer của tôi là bao nhiêu? – user2350858

+0

@ user2350858: Như tôi đã viết trong câu trả lời: stride là 8 * sizeof (GLfloat) (thường là 32) và offset 0 cho vị trí và 4 * sizeof (GLfloat) cho màu (như bạn đã làm) – derhass

15

Vì glVertexAttribPointer thường gây khó khăn, Tôi cố giải thích thêm ở đây.

Công thức để tính toán pos khởi đầu của thuộc tính thứ i trong mảng thuộc tính là:

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

Và giải thích trong đồ thị dưới đây: tightly packed arrtibute array


Nếu bạn cần ví dụ về mã, hãy tiếp tục đọc.

Từ Formatting VBO Data, chúng tôi biết chúng tôi có thể quản lý dữ liệu đỉnh của chúng tôi theo ba định dạng. Thực hiện một ví dụ về cách vẽ một hình tam giác, với màu vert và màu sắc kết cấu hỗn hợp, đây là cách để chuẩn bị dữ liệu thuộc tính vert:


# way1 thuộc tính Mỗi một VBO.

định dạng này như: (xyzxyz ...) (rgbrgb ...) (stst ....), và chúng ta có thể để cho cả hai sride = 0 và bù đắp = 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: Mỗi thuộc tính được tuần tự, được nhóm theo một VBO.

định dạng này là: (xyzxyzxyz ... rgbrgb ... ststst ...), chúng tôi có thể cho phép stride = 0 nhưng bù trừ phải được chỉ định.

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: Interleaved thuộc tính trong một đơn định dạng này VBO

giống như: (xyzrgbstxyzrgbst ...), chúng ta phải tự xác định bù đắp và sải chân.

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

Và cảm ơn câu trả lời của derhass.

+0

Wow, tôi đã cố gắng để bọc não của tôi xung quanh sự khác biệt của 3 phương pháp cho phần tốt hơn trong một ngày (chủ yếu xen kẽ với những người khác, và cách sử dụng bù đắp đúng cách), sau đó tôi thấy điều này, cạnh nhau, và tất cả trở nên rõ ràng. Cảm ơn. ;) Bất kỳ ý tưởng nào thường nhanh hơn? –

Các vấn đề liên quan