2016-09-16 18 views
0

Iは、とりわけ、以下の2つのメソッドがありQOpenGLWidgetから継承RenderWidgetクラスを持っている:ユーザがチェックボックスを切り替えたときsetSmthEnabledのみ呼び出されながらユーザー入力のみの一様変数を設定するにはどうすればよいですか?

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回/秒と呼ばれていますUI、ときどき発生します。 uniformUserInputユニフォームはフレームごとに設定する必要はないので、私はそれをユーザ入力スロットでのみ設定しようとしますが、動作しません。制服は値を保持し、初期化時に設定されます。

レンダリングが非同期であり、パイプラインがビジー状態のときにユニフォームを更新できないためです。だから私は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オブジェクトのQOpenGLShaderProgram::setUniformValueがコールされ、返されます。

答えて

2

ので、私は、ユーザーの入力スロットでそれを設定しようとするが、それは予想される

を動作しません。 OpenGLはステートフルAPIであり、状態はコンテキスト内にカプセル化されています。 1つのプログラムで使用されるコンテキストはいくつでもかまいません。バインドする必要があり、バインド解除できる必要があります。 Qtのプログラミングモデルを明確にするために、OpenGLコンテキストは、非常に特殊な状況、すなわち​​、paintGLおよびresizeGLの中でのみバインドされています。また、QOpenGLContext::makeCurrentでコンテキストを最新にすることもできます。

OpenGLコンテキストが現在バインドされている場合にのみ、それを使用できます。均一な値を設定するのと同じです。

これは、レンダリングが非同期であり、パイプラインがビジー状態のときにユニフォームを更新できないためです。

これはその理由ではありません。また、OpenGLは、いつでも任意の呼び出しを行うことができ、すべてがキューイングされるということが実際に指定されています。 GPUがレンダリングにテクスチャオブジェクトを使用している間でも(PBOを介して)テクスチャイメージを置き換えることもできます(ドライバはこれらの変更を追跡し、影響を受けるすべてのリソースを自由に使用できるようになるまで実行を延期する必要があります)。

+0

文脈が 'paintGL'では現在のものであることはわかりませんでしたが、私によって定義された他のメソッドではありません。あなたの答えは助けてくれました、ありがとう!しかし、いくつかの方法でしかコンテキストを最新にする根本的な理由は何ですか? 1つのアプリケーションで複数のコンテキストを管理することはできますか?それはレンダリングを大幅に遅くしませんか? – Sergey

+0

@Sergey:はい、これは、アプリケーション内に複数のコンテキストを持つ可能性についてです。デフォルトの動作モードでは、Qtはウィンドウごとに別々のコンテキストを作成します(Qt5とOpenGL統合の新しい方法では、他の方法でそれを行うことができますが、それほど単純ではありません)。したがって、コンテキストの周りに複数のOpenGLウィンドウがある場合は、切り替える必要があります。それに加えて、Qt5はUI要素をレンダリングするためにOpenGLを使用することもできますし、あなたのウィジェットは実際にはQtによって管理されるFBOで終わります。 – datenwolf

関連する問題