正如标题所示,我正在努力查找程序中错误的原因。glBindVertexArray()
在程序中绘制场景时会创建一个GL_INVALID_OPERATION,即使我事先已经正确初始化了它。
该程序在libQGLViewer库的帮助下使用了Qt 5.15。它由同一屏幕上的多个QGLViewer实例组成,并使用底层Scene
类从多个Qt窗口小部件中的相同缓冲区/纹理/VBO中绘制相同的内容。
Scene
类继承自QOpenGLFunction_4_0_Core
类,使其符合OpenGL 4.0,因此能够使用VAO/VBO。问题是:我有几个绘制函数,这取决于请求绘制的小部件的类型。以下是触发抽奖的代码概述:
// in viewer1.hpp :
class Viewer1 : public QGLViewer {
// ...
virtual void initGL() override; // Overrides QGLViewer's initGL function, similar to the QOpenGLWidget function of the same name
virtual void draw() override; // Overrides QGLViewer's draw function
protected:
Scene* scene;
// ...
}
// In viewer2.hpp :
class Viewer2 : public QGLViewer {
// ...
virtual void initGL() override; // Overrides QGLViewer's initGL function, similar to the QOpenGLWidget function of the same name
virtual void draw() override; // Overrides QGLViewer's draw function
protected:
Scene* scene;
// ...
}
// In scene.hpp :
void GetOpenGLError(); // <- Checks OpenGL error(s) and prints them, clearing the error state
class Scene : public QOpenGLFunctions_4_0_Core {
// ...
void initScene();
void drawFromViewer1(GLfloat* vMat, GLfloat* pMat);
void drawFromViewer2(GLfloat* vMat, GLfloat* pMat);
protected:
bool isInitialized;
GLuint vaoHandle;
// I have a special technique of volumetric drawing with difficult
// requirements which cannot be handled with the other VAO :
GLuint vaoHandle_volumetric;
// other opengl 'handles' (OpenGL names/IDs) to VBOs, textures ...
}
在我的initGL()
函数中,它所做的唯一一件事就是调用initScene()
函数,该函数检查场景是否已经使用Scene::isInitialized
布尔成员初始化(或开始初始化((因此场景不会初始化两次(。在initScene()
函数中,我调用this->initializeOpenGLFunctions()
,以便将Qt提供的OpenGL函数指针初始化为正确的值,这将允许我稍后在不同的查看器中绘制场景。说到这里,以下是不同绘图函数的代码概述:
void Scene::initScene() {
// ...
glGenVertexArrays(1, &this->vaoHandle);
GetOpenGLError(); // <- Prints nothing
glBindVertexArray(this->vaoHandle);
GetOpenGLError(); // <- Prints nothing
if (glIsVertexArray(this->vaoHandle) == GL_FALSE) {
throw std::runtime_error("VAO error in initScene()"); // <- doesn't get triggered
}
// Specify VAO state and pointers (...)
// ...
}
void Scene::drawFromViewer1(GLfloat* vMat, GLfloat* pMat) {
// Set the uniforms for the draw
glBindVertexArray(this->vaoHandle);
GetOpenGLError(); // <- Prints GL_INVALID_OPERATION !!!
// Draw after binding index buffer ...
// ...
}
void Scene::drawFromViewer2(GLfloat* vMat, GLfloat* pMat) {
// Set the uniforms for the draw
glBindVertexArray(this->vaoHandle);
GetOpenGLError(); // <- Prints GL_INVALID_OPERATION !!!
// Draw after binding index buffer ...
// ...
}
毫无意义的是,在VAO的创建/指定时,控制柄是有效的,但在绘制时不再有效!
在创建QMainWindow
/QApplication
之前,我确实调用了QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
,以便OpenGL查看器共享相同的上下文,但这并没有改变任何事情,每次绑定VAO时,操作都会返回GL_INVALID_OPERATION
,根据OpenGL规范,只有在之前没有使用对glGenVertexArrays()
/glBindVertexArrays()
的调用创建VAO时才会发生这种情况!
几天来,我断断续续地试图解决这个问题,但似乎无法解决。以前有人调试OpenGL/Qt程序的经验吗?似乎没有很多人在帮助论坛上使用最近的桌面OpenGL版本和Qt。。。
尽管顶点缓冲区对象可以在OpenGL上下文之间共享,顶点阵列对象不能:https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object