1

正如标题所示,我正在尝试找出程序中出现错误的原因。glBindVertexArray()在我的程序中绘制场景时创建一个 GL_INVALID_OPERATION,即使我事先已正确初始化它。

该程序在libQGLViewer库的帮助下使用 Qt 5.15 。它由同一屏幕上的多个 QGLViewer 实例组成,并使用底层Scene类从多个 Qt 小部件中的相同缓冲区/纹理/VBO 中绘制相同的内容。

该类Scene继承自QOpenGLFunction_4_0_Core该类,使其兼容 OpenGL 4.0,因此能够使用 VAO/VBO。问题是:我有几个绘图函数,具体取决于请求绘图的小部件类型。以下是触发 draw 的代码概述:

// 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 的创建/规范时,句柄是有效的,但在绘图时不再有效!

QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);我在创建QMainWindow/之前确实调用了QApplication,以便 OpenGL 查看器共享相同的上下文,但这并没有改变任何东西,每次绑定 VAO 时,操作总是返回GL_INVALID_OPERATION,根据 OpenGL 规范,只有在之前调用glGenVertexArrays()/没有创建 VAO glBindVertexArrays()

我断断续续地尝试了几天来解决这个问题,但我似乎无法解决它。有没有人有过调试 OpenGL/Qt 程序的经验?在帮助论坛上使用 Qt 的最新桌面 OpenGL 版本的人似乎并不多……

4

1 回答 1

0

虽然顶点缓冲区对象可以在 OpenGL 上下文之间共享,但顶点数组对象不能: https ://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object

于 2021-06-10T16:38:57.073 回答