今までのサンプルではテクスチャなどを画面に直接描画していましたが、これを画面ではなくフレームバッファと呼ばれる自分で作成したバッファに描画することができます(画面に描画するのも、デフォルトのフレームバッファに描画するということらしいですが)。
そんなことをして何が嬉しいのかと言いますと…
昨日のサンプルでは描画しているテクスチャは一枚だけでした。これがテクスチャなどの枚数が増えてくると、描画にいくらかの時間がかかるようになります。そうすると描画途中の絵が画面に出ることになり、絵がちらついたりします。
フレームバッファを使用する場合、絵は一旦フレームバッファに描画して、全て描画した後に画面に表示します。描画途中の絵が画面に出ることはないのでちらつきはありません。オフスクリーンレンダリングと呼ばれる方法です。
フレームバッファクラス sys::FrameBufferを見てみます。
FrameBuffer.h
#ifndef ___FRAME_BUFFER_H___
#define ___FRAME_BUFFER_H___
#include "common.h"
#include "Texture.h"
namespace sys
{
/********************************
フレームバッファテクスチャ
********************************/
class FrameBuffer : public Texture
{
GLuint frame_buffer; // フレームバッファオブジェクト
GLfloat mat_projection[4*4]; // 透視変換行列
public :
FrameBuffer(void) // コンストラクタ
{
frame_buffer = 0;
}
FrameBuffer(int _w, int _h)
{
make(_w, _h);
}
~FrameBuffer() // デストラクタ
{
clear();
}
void make(int, int); // 作成
void clear(void); // 削除
void bind(void); // 使用
};
}
#endif
/********************* End of File ********************************/
FrameBuffer.cpp
/*********************************************
フレームバッファテクスチャ
*********************************************/
#include "FrameBuffer.h"
#include "Renderer.h"
namespace sys
{
/********************************
作成
引数 _width = 幅
_height = 高さ
********************************/
void FrameBuffer::make(int _width, int _height)
{
glGenFramebuffers(1, &frame_buffer); // フレームバッファオブジェクト作成
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);
format = FORMAT_RGBA; // テクスチャフォーマット
width = _width; // 幅
height = _height; // 高さ
Texture::make(NULL); // テクスチャ作成
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); // フレームバッファにアタッチ
glBindFramebuffer(GL_FRAMEBUFFER, 0);
for (int i = 0; i < 4*4; i++) { // 透視変換行列初期化
mat_projection[i] = 0.0f;
}
mat_projection[0] = 2.0f/width;
mat_projection[5] = -2.0f/height;
mat_projection[10] = 1.0f;
mat_projection[15] = 1.0f;
}
/**********
削除
**********/
void FrameBuffer::clear(void)
{
if ( frame_buffer ) {
glDeleteFramebuffers(1, &frame_buffer);
frame_buffer = 0;
Texture::clear();
}
}
/**********
使用
**********/
void FrameBuffer::bind(void)
{
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);
glViewport(0, 0, width, height); // ビューポート設定
Renderer::mat_projection = mat_projection; // 透視変換行列設定
if ( Renderer::current_shader ) {
glUniformMatrix4fv(Renderer::current_shader->projection, 1, GL_FALSE, mat_projection);
}
}
}
/**************** End of File ******************************************/
セコメントをする