我目前正在尝试使用 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
,其中位置属性被发送到着色器并发出绘制调用。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);
}
现在我只尝试显示一个红色立方体(在片段着色器中),看看它是否有效。稍后我将专注于应用纹理。