読者です 読者をやめる 読者になる 読者になる

オフスクリーンレンダリングして画像書き出し

OpenGL

OpenGL で画面サイズ以上の画像を書き出す方法を大雑把にまとめ。
いまだ OpenGL 2.0 の環境なので glew の拡張機能を使っている。最近の環境では書き方が違うと思うが大体の流れは同じだと思う。

FBO を使うのでまず初期化する。よく見るのはレンダリング画像をテクスチャとして使うために FBO とテクスチャを関連づける方法だが、それは検索すればたくさんでてくる。ここでは画像保存しか扱わないのでテクスチャを使わずレンダーバッファのみ使う。

グローバル変数で frame buffer と render buffer のインデックスおよび画像サイズをそれぞれ

GLuint fbID, rbID;
int FB_WIDTH, FB_HEIGHT;

と定義している。

初期化関数の中で

glewInit();

// renderbuffer object の生成
glGenRenderbuffersEXT( 1, &rbID );
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

// 第二引数は 色 GL_RGB, GL_RGBA, デプス値 GL_DEPTH_COMPONENT, ステンシル値 GL_STENCIL_INDEX などを指定できる
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_RGBA, FB_WIDTH, FB_HEIGHT ); 

// framebuffer object の生成
glGenFramebuffersEXT( 1, &fbID );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbID );

// renderbufferをframebuffer objectに結びつける
// 第二引数は GL_COLOR_ATTACHMENTn_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_STENCIL_ATTACHMENT_EXT など
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbID );

glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );

よくあるのはレンダリング画像をテクスチャに使う場合で、その場合は

glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texID, 0 );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbID );

のようにテクスチャの方に色、レンダーバッファのほうにデプス値を割り当てるケースが多いようだが、ここではテクスチャは必要ないのでレンダーバッファのほうに色を直接割り当てている。ここから直接画像を読み取ることになる。

次に Display 関数のなかで

// fbo 有効化
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbID );

- 通常の描画

// 読み込むバッファを選ぶ
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);

- glReadPixels を用いて画像を保存する処理

// fbo 無効化
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0);

画像保存の処理は自作している人も多いし、検索すれば見つかるはずなので省略。