Qt GUI でフレームバッファの一部を無効化する: QOpenGLExtraFunctions::glInvalidateSubFramebuffer() の詳細


QOpenGLExtraFunctions::glInvalidateSubFramebuffer() 関数は、OpenGL フレームバッファの一部を無効化し、再描画を要求します。これは、フレームバッファの一部のみを更新する必要がある場合に役立ちます。

使用方法

void glInvalidateSubFramebuffer(GLenum target, GLuint numAttachments, const GLenum* attachments, GLuint x, GLuint y, GLuint width, GLuint height);
  • height: 無効化する領域の高さを指定します。
  • width: 無効化する領域の幅を指定します。
  • y: 無効化する領域の左下隅の Y 座標を指定します。
  • x: 無効化する領域の左下隅の X 座標を指定します。
  • attachments: 無効化するアタッチメントの配列を指定します。
  • numAttachments: 無効化するアタッチメントの数を指定します。
  • target: フレームバッファの種類を指定します。GL_FRAMEBUFFER が一般的です。

// フレームバッファオブジェクトをバインド
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// カラーアタッチメント 0 と深度アタッチメントを無効化
glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 2, (const GLenum[]){ GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT }, 0, 0, width, height);

// フレームバッファをアンバインド
glBindFramebuffer(GL_FRAMEBUFFER, 0);

このコードは、フレームバッファオブジェクト fbo のカラーアタッチメント 0 と深度アタッチメントを無効化します。その後、フレームバッファをアンバインドします。

  • 無効化するアタッチメントは、フレームバッファにアタッチされている必要があります。
  • 無効化する領域は、フレームバッファの境界内に収まる必要があります。
  • glInvalidateSubFramebuffer() 関数は OpenGL 4.3 以降でのみ使用できます。
  • OpenGL に関する詳細については、OpenGL 公式ドキュメントを参照してください。


#include <QApplication>
#include <QGLWidget>

class MyGLWidget : public QGLWidget
{
protected:
    void initializeGL() override
    {
        // OpenGL の初期化を行う

        // フレームバッファオブジェクトを作成
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);

        // カラーテクスチャを作成
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
        glGenerateMipmap(GL_TEXTURE_2D);

        // フレームバッファにカラーテクスチャをアタッチ
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

        // 深度バッファを作成
        glGenRenderbuffers(1, &depthRbo);
        glBindRenderbuffer(GL_RENDERBUFFER, depthRbo);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, width, height);

        // フレームバッファに深度バッファをアタッチ
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo);

        // フレームバッファの完全性を確認
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        {
            qFatal("フレームバッファの作成に失敗しました");
        }

        // OpenGL の初期化を完了
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glEnable(GL_DEPTH_TEST);
    }

    void paintGL() override
    {
        // フレームバッファをバインド
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);

        // クリアカラーでフレームバッファをクリア
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // 三角形を描画
        glBegin(GL_TRIANGLES);
        glVertex3f(-0.5f, -0.5f, 0.0f);
        glVertex3f( 0.5f, -0.5f, 0.0f);
        glVertex3f( 0.0f,  0.5f, 0.0f);
        glEnd();

        // フレームバッファの一部を無効化
        glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, &GL_COLOR_ATTACHMENT0, 0, 0, width / 2, height);

        // フレームバッファをアンバインド
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        // デフォルトのフレームバッファに描画
        glViewport(0, 0, width, height);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // フレームバッファテクスチャを描画
        glBindTexture(GL_TEXTURE_2D, texture);
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f,  1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f,  1.0f);
        glEnd();
    }

    void resizeGL(int w, int h) override
    {
        width = w;
        height = h;

        // フレームバッファのサイズに合わせてテクスチャと深度バッファを再構築
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2


glClearBufferSubData() を使用する

void glClearBufferSubData(GLenum target, GLenum internalformat, GLintptr offset, GLsizei size, GLenum format, GLenum type, const void* data);
  • data: 書き込むデータへのポインタを指定します。
  • type: データ型を指定します。
  • format: データの形式を指定します。
  • size: 書き込むデータのサイズを指定します。
  • offset: データを書き込むオフセットを指定します。
  • internalformat: フレームバッファ内のデータ形式を指定します。
  • target: フレームバッファの種類を指定します。GL_FRAMEBUFFER が一般的です。

// フレームバッファオブジェクトをバインド
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// カラーアタッチメント 0 の一部をクリア
glClearBufferSubData(GL_FRAMEBUFFER, GL_RGB, 0, width * height / 2 * 3, GL_RGB, GL_UNSIGNED_BYTE, nullptr);

// フレームバッファをアンバインド
glBindFramebuffer(GL_FRAMEBUFFER, 0);

このコードは、フレームバッファオブジェクト fbo のカラーアタッチメント 0 の上半分をクリアします。

glScissor() と glClear() を使用する

void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
void glClear(GLbitfield mask);
  • mask: クリアするビットマスクを指定します。GL_COLOR_BUFFER_BIT はカラーバッファをクリアし、GL_DEPTH_BUFFER_BIT は深度バッファをクリアします。
  • height: はさみ領域の高さを指定します。
  • width: はさみ領域の幅を指定します。
  • y: はさみ領域の左下隅の Y 座標を指定します。
  • x: はさみ領域の左下隅の X 座標を指定します。

// フレームバッファをバインド
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// はさみ領域を設定
glScissor(0, 0, width / 2, height);

// カラーバッファをクリア
glClear(GL_COLOR_BUFFER_BIT);

// はさみ領域を解除
glDisable(GL_SCISSOR_TEST);

// フレームバッファをアンバインド
glBindFramebuffer(GL_FRAMEBUFFER, 0);
  • glScissor()glClear() を使用する場合は、はさみ領域を解除する前に必ず忘れずに解除してください。
  • glClearBufferSubData() 関数は、フレームバッファ内のデータ形式と一致するデータのみを書き込むことができます。
  • OpenGL に関する詳細については、OpenGL 公式ドキュメントを参照してください。