0

我有一个RenderWidget继承自 的类QOpenGLWidget,它具有以下两种方法,其中包括:

RenderWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_3_Core {
    // ...
public slots:
    void setSmthEnabled(bool enabled) {
        float val = (enabled == true) ? 1.0f : 0.0f;
        shader.setUniformValue("uniformUserInput", val);
    }

public:
    void paintGL() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // ...
        shader.setUniformValue("uniform1", value1);
        shader.setUniformValue("uniform2", value2);
        // ...
        mesh->draw();
    }
};

paintGL每秒被调用 100 次,而setSmthEnabled仅在用户切换 UI 中的复选框时才调用,这种情况偶尔会发生。uniformUserInputuniform 不需要每帧都设置,所以我尝试只在用户输入槽中设置它,但它不起作用。制服保留了它的价值,这是在初始化时设置的。

我猜这是因为渲染是异步的,并且在管道繁忙时无法更新制服。这就是为什么我在glFinish()设置插槽之前尝试调用,但它没有帮助。我找到的唯一解决方案是以以下方式重写类:uniformUserInputsetSmthEnabled

RenderWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_3_Core {
    // ...
private:
    float val = 1.0f;

public slots:
    void setSmthEnabled(bool enabled) {
        val = (enabled == true) ? 1.0f : 0.0f;
    }

public:
    void paintGL() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // ...
        shader.setUniformValue("uniform1", value1);
        shader.setUniformValue("uniform2", value2);
        // ...
        shader.setUniformValue("uniformUserInput", val);
        mesh->draw();
    }
};

现实世界的代码包含更多的用户输入统一,因此我不想在每一帧都更新它们并为此保留冗余的成员变量。如何仅根据用户输入更新制服?

shader.setUniformValue在上面的核心中只调用QOpenGLShaderProgram::setUniformValue一个相关的QOpenGLShaderProgram对象并返回。

4

1 回答 1

2

所以我尝试只在用户输入槽中设置它,但它不起作用

这是可以预料的。OpenGL 是一个有状态的 API,状态被封装在一个上下文中。单个程序中可能使用任意数量的上下文,这些上下文必须是绑定的,也可以是未绑定的。为了在 Qt 的编程模型中清晰起见,OpenGL 上下文仅在非常特定的情况下绑定,即当insideinitializeGL和. 您也可以使用.paintGLresizeGLQOpenGLContext::makeCurrent

只有当 OpenGL 上下文绑定当前时,您才能使用它进行操作。就像设置统一的值一样。

我猜这是因为渲染是异步的,并且在管道繁忙时无法更新制服。

这不是原因。OpenGL 也完全有能力,事实上它被指定,你可以在任何时候拨打任何电话,一切都会排队。即使 GPU 仍在使用纹理对象进行渲染,您甚至可以替换纹理图像(甚至通过 PBO)(驱动程序必须跟踪这些更改并推迟执行,直到所有受影响的资源都可以自由使用)。

于 2016-09-16T10:58:33.597 回答