Не удается отобразить VBO с помощью простого куба, похоже, проблема с буферами

Попытка изменить это Учебное пособие по OpenGL и GLKit на raywenderlich.com. Я пытаюсь визуализировать куб из obj-файла волнового фронта без информации о цвете каждой вершины и с нормалями поверхности. Но то, что визуализируется, совсем не похоже на куб.

(Не)куб

Для анализа файла obj у меня есть метод (createDrawable), который проходит через obj и сохраняет информацию в структуру (Drawable), содержащую четыре вещи: буфер вершин, индексный буфер, количество граней в объекте и матрицу преобразования объекта. объект. (Вот заголовок, .m и файл .obj.)

- (Drawable)createDrawable: (NSString *)objFileName {
    ......
    ......

    // Parsed obj and put info in vertexData and indices arrays.

    Drawable _drawable;

    _drawable.numFaces = numFaces;

    glGenBuffers(1, &_drawable.vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _drawable.vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData) * numFaces * 8, vertexData, GL_STATIC_DRAW);

    glGenBuffers(1, &_drawable.indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _drawable.indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * numFaces * 3, indices, GL_STATIC_DRAW);

    _drawable.matrix = GLKMatrix4Identity;
    _drawable.matrix = GLKMatrix4Translate(_drawable.matrix, 0.0f, 0.0f, 10.0f);

    return _drawable;
}

Для рендеринга я использую другой метод (renderDrawable), который связывает буферы объекта, устанавливает на них указатели и затем рендерит с помощью glDrawElements(..).

- (void) renderDrawable: (Drawable)object {
    glBindBuffer(GL_ARRAY_BUFFER, object.vertexBuffer);
    glEnableVertexAttribArray(GLKVertexAttribPosition);        
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 0);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord1);
    glVertexAttribPointer(GLKVertexAttribTexCoord1, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 3);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 5);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object.indexBuffer);
    glDrawElements(GL_LINES, sizeof(object.indexBuffer) * 3 * object.numFaces, GL_UNSIGNED_BYTE, (const GLvoid *) object.indexBuffer);
}

Я думаю, что делаю что-то не так с буферами (часть createDrawable, показанная здесь, и renderDrawable в файле .m), но я просто не могу понять, что это такое.


person KK.    schedule 30.05.2012    source источник


Ответы (2)


Я думаю, что параметр "шаг" в glVertexArrayPointer должен быть установлен, например, на 8 * sizeof(float) (размер одной вершины)

glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (const GLvoid *) 5);

когда шаг равен 0, это означает, что атрибуты хранятся непрерывно... но у вас есть чередующиеся атрибуты, поэтому вы должны предоставить дополнительную информацию для OpenGL.

Другой вопрос: что такое sizeof(vertexData) * numFaces * 8... Я думаю, должно быть: sizeof(vertexData) * numFaces * 3

А для индексного буфера: sizeof(indices) * numFaces * 3 - думаю должно быть sizeof(int) * numFaces * 3

int — тип для индексов, но у вас GL_BYTE (это значит, что у вас может быть только 256 разных индексов!)

при рендеринге: glDrawArrays - у вас есть индексный буфер, поэтому установите последний параметр в NULL

person fen    schedule 30.05.2012
comment
sizeof(vertexData) * numFaces * 8 означало предоставление размера всего массива vertexData. На самом деле должно было быть sizeof(vertexData) * numFaces * 8 * 3, потому что должно быть 3 вершины на грань и 8 значений с плавающей запятой (3V, 2T и 3N) на вершину. Использование последнего делает видимыми больше граней, но не для куба. Также я изменил тип индексов на uint. - person KK.; 30.05.2012
comment
да да... Я быстро написал этот ответ, и были некоторые ошибки :) Надеюсь, это помогло - person fen; 30.05.2012
comment
Конечно, это помогло. Это помогло мне по-новому взглянуть на вещи. Спасибо за помощь. - person KK.; 01.06.2012

Я думаю, ваша проблема в том, что вы передаете GL_LINES в glDrawElements() вместо GL_TRIANGLES.

person Tobias Schlegel    schedule 30.05.2012
comment
Нет. На самом деле при передаче GL_TRIANGLES на экране ничего не появляется. Я просто был сыт по горло и случайным образом делал настройки, когда заметил, что передача GL_LINES заставляет по крайней мере «что-то» появиться. (В идеале, я думаю, общая форма должна быть одинаковой) - person KK.; 30.05.2012
comment
Нет, форма будет совершенно другой, потому что GL_LINES принимает две вершины на линию, а GL_TRIANGLES — три вершины на полигон. - person Tobias Schlegel; 30.05.2012
comment
Ok. Я этого не знал. Это означает, что при использовании GL_TRIANGLES на экране ничего не рисуется. - person KK.; 30.05.2012