如何仅在用户输入时设置统一变量?

How to set a uniform variable on user input only?

我有一个RenderWidget class继承自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 times/second,而 setSmthEnabled 仅在用户切换 UI 中的复选框时才被调用,这偶尔会发生。 uniformUserInput uniform 不需要每一帧都设置,所以我尝试只在用户输入槽中设置它,但它不起作用。制服保留其在初始化时设置的值。

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

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 对象和 returns.

so I try to set it only in user input slot, but it does not work

这是意料之中的事情。 OpenGL 是有状态的 API 并且状态被封装在上下文中。一个程序中可能会使用任意数量的上下文,这些上下文必须是绑定的,也可以是非绑定的。为了清楚 Qt 的编程模型,OpenGL 上下文仅在非常特定的情况下绑定,即在 initializeGLpaintGLresizeGL 内。您还可以使用 QOpenGLContext::makeCurrent.

使上下文成为当前上下文

只有当 OpenGL 上下文绑定为当前上下文时,您才能使用它执行操作。喜欢设置统一值。

I guess this happens because rendering is asynchronous, and uniform cannot be updated while the pipeline is busy.

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