OpenGL ES/3.x/4.xで知っておくべきこと:QOpenGLExtraFunctions::glEndTransformFeedback() 関数


QOpenGLExtraFunctions::glEndTransformFeedback() 関数は、OpenGL ES 3.x、OpenGL 3.x または 4.x コンテキストで使用される、トランスフォームフィードバックの終了を知らせる関数です。トランスフォームフィードバックは、頂点シェーダーの出力データを、別のバッファオブジェクトに書き込むためのOpenGL機能です。

機能

この関数は、現在実行中のトランスフォームフィードバックパイプラインを終了します。パイプラインが終了すると、頂点シェーダーの出力データは、指定されたバッファオブジェクトに書き込まれなくなります。

プロトタイプ

void QOpenGLExtraFunctions::glEndTransformFeedback();

パラメータ

この関数にはパラメータはありません。

戻り値

この関数は、void 型の値を返します。

使用例

// トランスフォームフィードバックパイプラインを開始します。
glBeginTransformFeedback(GL_TRANSFORM_FEEDBACK);

// 頂点シェーダーを実行します。

// トランスフォームフィードバックパイプラインを終了します。
glEndTransformFeedback();
  • トランスフォームフィードバックパイプラインが開始されていない場合は、この関数を呼び出すとエラーが発生します。
  • プレーンな OpenGL で使用するには、指定されたプロファイルとバージョンが、コアまたは拡張機能としてこの関数をサポートしている必要があります。
  • この関数は、OpenGL ES 3.x、OpenGL 3.x または 4.x コンテキストでのみ使用できます。
  • この関数は、パフォーマンスを向上させるために使用できます。
  • この関数は、ジオメトリシェーダーの出力データを書き込むためにも使用できます。
  • この関数は、頂点バッファオブジェクト (VBO) の更新に使用できます。


#include <QCoreApplication>
#include <QOpenGLFunctions>
#include <QOpenGLWidget>

class MyWidget : public QOpenGLWidget {
public:
    MyWidget() : QOpenGLWidget() {}

protected:
    void initializeGL() override {
        // OpenGL ES 3.x コンテキストを取得します。
        QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();

        // 頂点シェーダーとフラグメントシェーダーを作成します。
        QOpenGLShaderProgram program;
        program.addShaderFromSourceFile(QVertexShader, "vertex.vert");
        program.addShaderFromSourceFile(QFragmentShader, "fragment.frag");
        program.link();

        // 頂点バッファオブジェクト (VBO) を作成し、データを初期化します。
        GLuint vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);

        GLfloat vertices[] = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f
        };

        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        // トランスフォームフィードバックオブジェクト (TBO) を作成します。
        GLuint tbo;
        glGenBuffers(1, &tbo);
        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);

        // TBO に出力データ書き込むために必要なバッファレイを構成します。
        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tbo);
        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
        glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(GLfloat) * 3, nullptr, GL_STATIC_DRAW);

        // トランスフォームフィードバックパイプラインを開始します。
        glBeginTransformFeedback(GL_TRANSFORM_FEEDBACK);

        // 頂点シェーダーを実行します。
        program.bind();
        glDrawArrays(GL_TRIANGLES, 0, 3);
        program.release();

        // トランスフォームフィードバックパイプラインを終了します。
        glEndTransformFeedback();

        // バインディングを解除します。
        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
    }
};

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    MyWidget widget;
    widget.show();

    return app.exec();
}

このコードの説明

  1. initializeGL() 関数は、OpenGL コンテキストの初期化、シェーダープログラムの作成、VBO と TBO の作成、トランスフォームフィードバックパイプラインの設定、頂点シェーダーの実行、パイプラインの終了、バインディングの解除を行います。
  2. glBeginTransformFeedback() 関数は、トランスフォームフィードバックパイプラインを開始します。
  3. program.bind(); 行は、頂点シェーダープログラムをバインドします。
  4. glDrawArrays(GL_TRIANGLES, 0, 3); 行は、VBO に格納された頂点データを使用して、三角形を描画します。
  5. program.release(); 行は、頂点シェーダープログラムのバインディングを解除します。
  6. glEndTransformFeedback() 関数は、トランスフォームフィードバックパイプラインを終了します。
  1. Qt Creator などの IDE を使用して、Qt プロジェクトを作成します。
  2. プロジェクトをビルドして実行します。
  • 実際のアプリケーションでは、ニーズに合わせてコード


この関数の代替方法として、以下の方法が考えられます。

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0) を使用する方法

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0) 関数は、現在のトランスフォームフィードバックオブジェクト (TBO) のバインディングを解除します。これにより、トランスフォームフィードバックパイプラインが終了されます。

// トランスフォームフィードバックパイプラインを開始します。
glBeginTransformFeedback(GL_TRANSFORM_FEEDBACK);

// 頂点シェーダーを実行します。

// トランスフォームフィードバックパイプラインを終了します。
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

glFlush() を使用する方法

glFlush() 関数は、すべての未完了のグラフィックコマンドを処理し、グラフィックパイプラインからバッファに書き込みます。これにより、トランスフォームフィードバックパイプラインも終了されます。

// トランスフォームフィードバックパイプラインを開始します。
glBeginTransformFeedback(GL_TRANSFORM_FEEDBACK);

// 頂点シェーダーを実行します。

// トランスフォームフィードバックパイプラインを終了します。
glFlush();

glEnd() を使用する方法

glEnd() 関数は、現在のプリミティブ描画を終了します。トランスフォームフィードバックパイプラインがプリミティブ描画の一部である場合は、この関数もパイプラインを終了します。

// トランスフォームフィードバックパイプラインを開始します。
glBeginTransformFeedback(GL_TRANSFORM_FEEDBACK);

// 頂点シェーダーを実行します。

// プリミティブ描画を終了します。
glEnd();

注意事項

  • トランスフォームフィードバックパイプラインが開始されていない場合は、これらの代替方法を呼び出すとエラーが発生します。
  • プレーンな OpenGL で使用するには、指定されたプロファイルとバージョンが、コアまたは拡張機能としてこれらの代替方法をサポートしている必要があります。
  • 上記の代替方法は、OpenGL ES 3.x、OpenGL 3.x または 4.x コンテキストでのみ使用できます。
  • 代替方法は、パフォーマンスを向上させるために使用できます。
  • QOpenGLExtraFunctions::glEndTransformFeedback() 関数は、より明確で簡潔なコードを書くために使用できます。
  • パフォーマンスを重視する場合は、代替方法を使用することを検討してください。
  • コードの可読性と簡潔性を重視する場合は、QOpenGLExtraFunctions::glEndTransformFeedback() 関数を使用することをお勧めします。