我目前正在尝试使用Qt的QOpenGL库渲染天空盒。为此,我试图修改Qt提供的QOpenGL“多维数据集”示例(我使用的是最新的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
方法中隔离了原点,将position属性发送到着色器并发出了draw调用。 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);
}
现在,我仅尝试显示一个红色立方体(在片段着色器中)以查看其是否起作用。稍后我将重点介绍应用纹理。