Ошибка QOpenGL: "Неправильное использование VAO/VBO/ указателя" "Объект массива не активен"
В настоящее время я пытаюсь визуализировать скайбокс, используя библиотеку QOpenGL Qt. Для этого я попытался изменить пример "куба" QOpenGL, предоставленного Qt (я использую последнюю версию Qt 5.13).
Буферы вершин и индексов инициализируются в классе GeometryEngine
, в котором вершина и индексный массив также определены. В этом примере массив вершин имеет координаты текстуры, поэтому я избавился от них и сохранил только координаты позиции, потому что каждая операция, связанная с текстурой скайбокса, будет выполняться в шейдерах.
Там также есть функция под названием initTextures
в классе окна, который я изменил, чтобы загрузить текстуры 6 граней куба (хотя я не знаю, верна ли эта часть).
Я также настроил регистратор отладки OpenGL, используя этот пример: https://www.trentreed.net/blog/qt5-opengl-part-5-debug-logging/.
Когда я выполняю код, я получаю только окно с черным экраном и ничего не отображается, и следующие сообщения об ошибках: GL_INVALID_OPERATION error generated. Invalid VAO/VBO/pointer usage.
а такжеGL_INVALID_OPERATION error generated. Array object is not active.
Кто-нибудь сталкивался с этой проблемой раньше и исправил ее? Потому что я не думаю, что я забыл какую-либо часть процесса рендеринга. Я только изменил входные данные и шейдеры (но я не получил ошибки от этой части).
Во-первых, я думал, что суть проблемы связана с массивом вершин и индексов, поэтому я попытался использовать только буфер вершин, повторяя вершины для каждого треугольника в массиве вершин, но я получил те же сообщения об ошибках.
Так как я не получил ошибку компиляции, я попытался найти проблему с помощью #if 0 [...] #endif
на каждой функции, пока я не получил сообщений об ошибках OpenGL. Я наконец изолировал происхождение в drawCubeGeometry
метод в GeometryEngine
класс, где атрибут позиции отправляется шейдерам и вызывается вызов отрисовки. Кажется, есть проблема с setAttributeBuffer
а также glDrawElements
звонки, но я не могу понять это.
Я пытался искать решения в Интернете, но о QOpenGL задали так мало вопросов.
В GeometryEngine.cpp:
void GeometryEngine::initCubeGeometry()
{
QVector3D vertices[] = {
// Vertex data for face 0
QVector3D(-1.0f, -1.0f, 1.0f), // v0
QVector3D( 1.0f, -1.0f, 1.0f), // v1
QVector3D(-1.0f, 1.0f, 1.0f), // v2
QVector3D( 1.0f, 1.0f, 1.0f), // v3
// Vertex data for face 1
QVector3D( 1.0f, -1.0f, 1.0f), // v4
QVector3D( 1.0f, -1.0f, -1.0f), // v5
QVector3D( 1.0f, 1.0f, 1.0f), // v6
QVector3D( 1.0f, 1.0f, -1.0f), // v7
// Vertex data for face 2
QVector3D( 1.0f, -1.0f, -1.0f), // v8
QVector3D(-1.0f, -1.0f, -1.0f), // v9
QVector3D( 1.0f, 1.0f, -1.0f), // v10
QVector3D(-1.0f, 1.0f, -1.0f), // v11
// Vertex data for face 3
QVector3D(-1.0f, -1.0f, -1.0f), // v12
QVector3D(-1.0f, -1.0f, 1.0f), // v13
QVector3D(-1.0f, 1.0f, -1.0f), // v14
QVector3D(-1.0f, 1.0f, 1.0f), // v15
// Vertex data for face 4
QVector3D(-1.0f, -1.0f, -1.0f), // v16
QVector3D( 1.0f, -1.0f, -1.0f), // v17
QVector3D(-1.0f, -1.0f, 1.0f), // v18
QVector3D( 1.0f, -1.0f, 1.0f), // v19
// Vertex data for face 5
QVector3D(-1.0f, 1.0f, 1.0f), // v20
QVector3D( 1.0f, 1.0f, 1.0f), // v21
QVector3D(-1.0f, 1.0f, -1.0f), // v22
QVector3D( 1.0f, 1.0f, -1.0f) // v23
};
GLushort indices[] = {
0, 1, 2, 3, 3,
4, 4, 5, 6, 7, 7,
8, 8, 9, 10, 11, 11,
12, 12, 13, 14, 15, 15,
16, 16, 17, 18, 19, 19,
20, 20, 21, 22, 23
};
// Transfer vertex data to VBO 0
arrayBuf.bind();
arrayBuf.allocate(vertices, 24 * sizeof(QVector3D));
// Transfer index data to VBO 1
indexBuf.bind();
indexBuf.allocate(indices, 34 * sizeof(GLushort));
}
void GeometryEngine::drawCubeGeometry(QOpenGLShaderProgram *program)
{
// Tell OpenGL which VBOs to use
arrayBuf.bind();
indexBuf.bind();
// Offset for position
quintptr offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = program->attributeLocation("a_position");
program->enableAttributeArray(vertexLocation);
program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(QVector3D));
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0);
}
GLWidget.cpp:
void GLWidget::paintGL()
{
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
texture->bind();
// Calculate model view transformation
QMatrix4x4 matrix;
matrix.translate(0.0, 0.0, 0.0);
matrix.rotate(rotation);
// Set modelview-projection matrix
program.setUniformValue("mvp_matrix", projection * matrix);
// Use texture unit 0 which contains cube.png
program.setUniformValue("texture", 0);
// Draw cube geometry
geometries->drawCubeGeometry(&program);
}
Пока я только пытаюсь отобразить красный куб (в фрагментном шейдере), чтобы увидеть, работает ли он. Я сосредоточусь на применении текстуры позже.