サーチ…
フレームバッファの基本
フレームバッファは、メモリ内のピクセルのカラー値、 深さおよびステンシル情報を格納するバッファのタイプです。 OpenGLで何かを描画すると、出力はデフォルトのフレームバッファに格納され、実際に画面上にこのバッファのカラー値が表示されます。 グレースケール、ぼかし、被写界深度、歪み、反射など、多くのクールなポストプロセッシングエフェクトに使用できる独自のフレームバッファを作成することもできます。
まず、フレームバッファオブジェクト( FBO )を作成し、OpenGLの他のオブジェクトと同様にバインドする必要があります。
unsigned int FBO;
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
フレームバッファに少なくとも1つの添付ファイル (色、深さ、またはステンシル)を追加する必要があります。添付ファイルは、フレームバッファのバッファとして機能するメモリロケーションです。これは、 テクスチャまたはレンダバッファオブジェクトです。テクスチャを使用する利点は、後処理シェーダでこのテクスチャを簡単に使用できることです。テクスチャの作成は、通常のテクスチャと似ています。
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
width
とheight
はレンダリングウィンドウのサイズと同じにする必要があります。テクスチャデータポインタは、メモリを割り当てたいだけで、テクスチャにはデータを入れないため、 NULL
なります。テクスチャは準備ができているので、実際にフレームバッファに取り付けることができます:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
フレームバッファはすぐに使用できるようになっているはずですが、深度アタッチメント、または深度とステンシルアタッチメントを追加することもできます。それらをテクスチャアタッチメントとして追加したい場合(そしてそれらを何らかの処理に使用する場合)、上記のような別のテクスチャを作成することができます。唯一の違いは次のようなことです。
glTexImage2D(
GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, NULL
);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
または、これらを単一のテクスチャで深さとステンシルのアタッチメントを使用する場合:
glTexImage2D(
GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL
);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
後で値を処理したくない場合は、テクスチャの代わりにレンダバッファを使用して、深度バッファとステンシルバッファの添付ファイルとして使用することもできます。 (別の例で説明します...)
フレームバッファが正常に作成され、エラーなしで完了したかどうかを確認できます。
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
// do something...
最後に、フレームバッファをアンバインドして、間違ってレンダリングしないようにしてください。
glBindFramebuffer(GL_FRAMEBUFFER, 0);
限界
単一のフレームバッファに接続できるカラーバッファの最大数は、パラメータGL_MAX_COLOR_ATTACHMENTS
を使用して、OGL関数glGetIntegervによって決定できます。
GLint maxColAttchments = 0;
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, &maxColAttchments );
フレームバッファを使用する
使い方はかなり簡単です。まず、 フレームバッファをバインドしてシーンをレンダリングします。しかし、レンダーバッファーが見えないため、実際には何も見えません。したがって、2番目の部分は、フレームバッファを画面全体のクワッドのテクスチャとしてレンダリングすることです。そのままレンダリングしたり、後処理効果を加えたりすることができます。
フルスクリーンクワッドの頂点は次のとおりです。
float vertices[] = {
// positions texture coordinates
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
それらをVBOに格納するか、属性ポインタを使用してレンダリングする必要があります。テクスチャでフルスクリーンクワッドをレンダリングするための基本的なシェーダプログラムも必要になります。
頂点シェーダ:
in vec2 position;
in vec2 texCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
TexCoords = texCoords;
}
フラグメントシェーダ:
in vec2 TexCoords;
out vec4 color;
uniform sampler2D screenTexture;
void main()
{
color = texture(screenTexture, TexCoords);
}
注意: GLSLのバージョンのシェーダを調整する必要があるかもしれません。
これで実際のレンダリングを行うことができます。上記のように、まずシーンをFBOにレンダリングします。これを行うには、単にFBOをバインドしてクリアし、シーンを描画します。
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw your scene here...
注意: glClear
関数では、使用しているすべてのフレームバッファアタッチメントを指定する必要があります(この例では、色と深さのアタッチ)。
これで、FBOをデフォルトのフレームバッファ上でフルスクリーンのクワッドとしてレンダリングできるようになりました。これを行うには、単にFBOのバインドを解除し、クワッドをレンダリングします:
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind your FBO to set the default framebuffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Use(); // shader program for rendering the quad
glBindTexture(GL_TEXTURE_2D, texture); // color attachment texture
glBindBuffer(GL_ARRAY_BUFFER, VBO); // VBO of the quad
// You can also use VAO or attribute pointers instead of only VBO...
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
それだけです!すべてを正しく行った場合は、以前と同じシーンが表示されますが、フルスクリーンのクワッドに表示されるはずです。ビジュアル出力は以前と同じですが、フラグメントシェーダーを編集するだけで後処理エフェクトを簡単に追加できます。 (別の例でエフェクトを追加してここにリンクします)