у меня есть 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
вызывается только тогда, когда пользователь устанавливает флажок в пользовательском интерфейсе, что иногда происходит. uniformUserInput
Равномерный не нужно устанавливать каждый кадр, поэтому я пытаюсь установить его только в пользовательском слоте ввода, но это не работает. Униформа сохраняет свое значение, которое было установлено при инициализации.
Я предполагаю, что это происходит потому, что рендеринг является асинхронным, и униформа не может быть обновлена, пока конвейер занят. Вот почему я пытался позвонить glFinish()
перед установкой uniformUserInput
в setSmthEnabled
слот, но это не помогло. Единственное решение, которое я нашел, — переписать класс следующим образом:
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
объект и возвращается.
поэтому я пытаюсь установить его только в пользовательском слоте ввода, но он не работает
Что и следовало ожидать. OpenGL является API-интерфейсом с полным состоянием, и состояние инкапсулируется в контекст. В одной программе может использоваться любое количество контекстов, которые должны быть связаны и могут быть не связаны. для ясности в модели программирования Qt контекст OpenGL ограничен только в очень специфических обстоятельствах, а именно когда внутри initializeGL
, paintGL
а также resizeGL
, Также вы можете сделать контекст текущим с QOpenGLContext::makeCurrent
,
Только когда контекст OpenGL привязан к текущему, вы можете с ним что-то делать. Как и установка одинаковых значений.
Я предполагаю, что это происходит потому, что рендеринг является асинхронным, и униформа не может быть обновлена, пока конвейер занят.
Это не причина. Кроме того, OpenGL вполне способен, фактически указано, что вы можете сделать любой вызов в любое время, и все встает в очередь. Вы даже можете заменить текстурные изображения (даже через PBO), даже если графический процессор все еще использует объект текстуры для рендеринга (драйвер должен отслеживать эти изменения и откладывать выполнение, пока все затронутые ресурсы не будут свободны для использования).
Других решений пока нет …