提问人:Thibault de Villèle 提问时间:1/13/2021 更新时间:6/11/2021 访问量:323
Qt + OpenGL4 : glBindVertexArray() 在绘图时创建一个GL_INVALID_OPERATION
Qt + OpenGL4 : glBindVertexArray() creates a GL_INVALID_OPERATION when drawing
问:
正如标题所暗示的那样,我正在尝试找到程序中错误的原因。 在我的程序中绘制场景时创建一个GL_INVALID_OPERATION,即使我事先已经正确初始化了它。glBindVertexArray()
该程序使用 Qt 5.15,并借助 libQGLViewer 库。它由同一屏幕上的多个QGLViewer实例组成,并使用底层类从多个Qt小部件中的相同缓冲区/纹理/VBO中绘制相同的内容。Scene
该类继承自该类,使其符合 OpenGL 4.0,因此能够使用 VAO/VBO。问题来了:我有几个绘制函数,具体取决于要求绘制的小部件的类型。以下是触发绘制的代码的概述:Scene
QOpenGLFunction_4_0_Core
// 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 ...
}
在我的函数中,它唯一要做的一件事就是调用该函数,该函数检查场景是否已经使用布尔成员初始化(或开始初始化)(因此场景不会初始化两次)。在函数中,我调用是为了让 Qt 提供的 OpenGL 函数指针初始化为正确的值,这将允许我在不同的查看器中绘制场景。说到这里,以下是不同绘制函数的代码概述:initGL()
initScene()
Scene::isInitialized
initScene()
this->initializeOpenGLFunctions()
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 的创建/规范时,手柄是有效的,但在绘图时就不再有效了!
我确实在创建我的 / 之前调用了 opengl 查看器,以便 OpenGL 查看器共享相同的上下文,但这并没有改变任何事情,每次绑定 VAO 时,操作总是返回,根据 OpenGL 规范,这只有在 VAO 未创建时才会发生之前对 / 的调用!QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QMainWindow
QApplication
GL_INVALID_OPERATION
glGenVertexArrays()
glBindVertexArrays()
我已经断断续续地尝试了几天来解决这个问题,但我似乎无法解决它。以前有没有人有过调试OpenGL / Qt程序的经验?在帮助论坛上,似乎没有多少人使用最新的桌面OpenGL版本和Qt......
答:
尽管顶点缓冲区对象可以在 OpenGL 上下文之间共享, 顶点数组对象不能: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
评论
glBindVertexArray
initScene()
QOpenGLContext
isValid()
QOpenGLWidget::context()