Поскольку glVertexAttribPointer часто создает проблемы, я попытаюсь объяснить это здесь.
Формула для вычисления начальной позиции i-го атрибута в массиве атрибутов:
startPos(i) = offset + i * stride
(из другого ответа Дерхасса)
И поясняется на графике ниже:
Если вам нужен пример кода, продолжайте читать.
Из Форматирование данных VBO мы знаем, что можем управлять данными вершин в трех форматах. Сделайте пример рисования треугольника со смешанным цветом вершины и цветом текстуры, вот способ подготовки данных атрибута вершины:
#way1 Каждый атрибут VBO.
этот формат, например: (xyzxyz...)(rgbrgb...)(stst....), и мы можем указать как sride = 0, так и 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: каждый атрибут является последовательным и группируется в одном VBO.
этот формат выглядит следующим образом: (xyzxyzxyz... rgbrgb... ststst...), мы можем оставить шаг=0, но нужно указать смещение.
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(GLfloat)
glEnableVertexAttribArray(0);
// specify color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(9 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// specify texture coordinate
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(18 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
VBOIdVec.push_back(VBOId);
}
#way3: чередование атрибутов в одном VBO
этот формат похож на: (xyzrgbstxyzrgbst...), мы должны вручную указать смещение и шаг.
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(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// specify color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
8 * sizeof(GLfloat),(GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// specify texture coordinate
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE,
8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
VBOIdVec.push_back(VBOId);
}
И спасибо за ответ Дерхасса.
25.09.2016
sizeof(GL_FLOAT)
выглядит некорректно и работает случайно. Должно бытьsizeof(GLfloat)
28.11.2018