フレームバッファ
フレームバッファを利用することによって実現できる代表的な処理にオフスクリーンレンダリングがあります。
これは読んで字の如く、スクリーンには表示されないレンダリングのことで、
バックグラウンドでメモリ空間上に粛々とレンダリングを行なうことが可能になります。
一度バックグラウンドでレンダリングした風景を、そのまま背景用のテクスチャとして利用するなど
フレームバッファは、
色を扱うためのカラーバッファや、
深度を扱う深度バッファ(デプスバッファ)、
ステンシルバッファなどを内包しています
バッファをまとめたもの
正確には、フレームバッファに対して求める性能によって、紐付けするためのバッファをどこまで用意するのかは変わってきます。
たとえば、厳密に言えば、深度テストや深度に関する情報が必要ないのなら深度バッファは必要ありませんよね。
それならフレームバッファにわざわざ深度バッファを紐付けする必要はありません。
要するに、フレームバッファをどのように扱うのかはプログラマの裁量によって自由に調整できるわけですね。
例
フレームバッファを生成する
色を扱うためのバッファを生成する
深度を扱うためのバッファを生成する
二つのバッファをフレームバッファに紐付ける
完成したフレームバッファにレンダリング
レンダーバッファ、またはテクスチャをフレームバッファへアタッチする
code:js
// フレームバッファの生成
var frameBuffer = gl.createFramebuffer();
// フレームバッファをWebGLにバインド
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
続いて、フレームバッファにレンダーバッファやテクスチャを紐付けます。今回は、深度バッファとしてレンダーバッファを、カラーバッファとしてテクスチャを使う想定で見てみます。
レンダーバッファの場合
フレームバッファにレンダーバッファを深度バッファとして関連付ける
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderBuffer);
第一引数にはgl.FRAMEBUFFERを指定し、
第二引数には紐付けするレンダーバッファをどのようなフォーマットとするかを定数値で指定します。
第三引数にはgl.RENDERBUFFERを、第四引数には紐付けするレンダーバッファを渡します。
第二引数に指定できるフォーマットには、以下のものが使えます。
table:フォーマット
フォーマット 意味
gl.COLOR_ATTACHMENT0 カラーバッファとしてアタッチ
gl.DEPTH_ATTACHMENT 深度バッファとしてアタッチ
gl.STENCIL_ATTACHMENT ステンシルバッファとしてアタッチ
テクスチャの場合
テクスチャをフレームバッファに紐付けする場合には、専用のメソッドを使います。
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
第一引数、第二引数までは、レンダーバッファのときと同様に指定すれば大丈夫です。
第三引数には、紐付けするテクスチャのフォーマットを指定しますので、通常はgl.TEXTURE_2Dを指定します。
第四引数はフレームバッファに紐付けるテクスチャオブジェクト、
第五引数はテクスチャレベルなので通常 0 を指定すれば問題ないでしょう。
テクスチャへのレンダリング
冒頭で書いたように、WebGL には既定で暗黙のフレームバッファが設定されています。特別な指定を行なわない場合、自動的にこの既定のフレームバッファが使われます。利用するフレームバッファを切り替えるには、単純にフレームバッファをバインドするだけで大丈夫です。
バインドを解除すると、再び既定のフレームバッファが使われるようになります。
code:js
// フレームバッファをバインド
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
// フレームバッファのバインドを解除
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
既定のフレームバッファを使う場合には、最後にコンテキストをリフレッシュするためにflushメソッドを実行する必要がありましたが、自前のフレームバッファでは必ずしも行なわなくても大丈夫です。フレームバッファのバインドが解除された時点で、自動的にフレームバッファ上のレンダリングは更新されます。
...