Frame Buffer Objectについて

FBOとは

OpenGL - PBOでPBOについて説明しました. PBOはピクセルデータを格納するGPU側のバッファであり,これを利用してフレームバッファからデータを転送していました. フレームバッファは,OpenGLのレンダリングパイプラインにおいて最終的なレンダリング結果を描画するのに用いられ, システムにもよりますが一般的に,複数のカラーバッファ,デプスバッファ,ステンシルバッファ,アキュムレーションバッファの 集合になっています. このフレームバッファをオフラインで用いることができるのがFrame buffer object(FBO)です. フレームバッファと同じように,FBOもカラー,デプス,ステンシルバッファを持ちます(アキュムレーションバッファはサポートされていないようです). また,FBOではrenderbuffer object(RBO)とテクスチャオブジェクトを関連付けることで, テクスチャへのレンダリングが可能となります.

FBOの使い方

FBOのIDや関連付けたRBO,テクスチャをまとめて管理するために以下のような構造体を作成します.

  1
  2
  3
  4
  5
  6
  7
  8
  9
struct RxFBO
{
    GLuint id;            int w, h, c;        int size;            GLuint tex;            GLuint rboid;    };

FBOの作成手順

  1. glGenFramebufferでFBO生成
    void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
  2. glBindFramebufferでバインド
    void glBindFramebuffer(GLenum target, GLuint framebuffer);
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22

void CreateFBO(RxFBO &fbo)
{
        glGenRenderbuffers(1, &fbo.rboid);
    glBindRenderbuffer(GL_RENDERBUFFER, fbo.rboid);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fbo.w, fbo.h);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
 
        glGenFramebuffers(1, &fbo.id);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
 
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.tex, 0);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo.rboid);
 
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

FBOの破棄

glDeleteFramebuffersを用いる.

void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11

void DeleteFBO(RxFBO &fbo)
{
    glDeleteFramebuffers(1, &fbo.id);
    glDeleteRenderbuffersEXT(1, &fbo.rboid);
    fboid = 0;
    rboid = 0;
}

FBOの使用例

PBOの時のように,FBOを介してテクスチャをターゲットにして描画して, それを貼り付けたポリゴンを描画します.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
RxFBO g_fboScreen;
 
void RenderSceneWithFBO(RxFBO &fbo)
{
    if(!fbo.id) return;
 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
 
    glViewport(0, 0, fbo.w, fbo.h);
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(RX_FOV, (float)(fbo.w/fbo.h), 0.2f, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
 
    RenderScene();
 
    glFlush();
 
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
    glBindTexture(GL_TEXTURE_2D, fbo.tex);
    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
}
 
void RenderImage(RxFBO &fbo)
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glViewport(0, 0, g_iWinW, g_iWinH);
 
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    //glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    Projection();
 
    glMatrixMode( GL_MODELVIEW);
    glLoadIdentity();
 
    glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
    glBindTexture(GL_TEXTURE_2D, fbo.tex);
 
    glPushMatrix();
 
    g_tbView.TrackballApply();     
    glColor4d(0.0, 0.0, 1.0, 1.0);
    glBegin(GL_QUADS);
    glTexCoord2d(0.0, 1.0);    glVertex3d(-0.8,  0.8, 0.0);
    glTexCoord2d(1.0, 1.0);    glVertex3d( 0.8,  0.8, 0.0);
    glTexCoord2d(1.0, 0.0);    glVertex3d( 0.8, -0.8, 0.0);
    glTexCoord2d(0.0, 0.0);    glVertex3d(-0.8, -0.8, 0.0);
    glEnd();
    glPopMatrix();
 
    glBindTexture(GL_TEXTURE_2D, 0);
 
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
 
    glDisable(GL_TEXTURE_2D);
 
    glutSwapBuffers();
}
 
void Display(void)
{
    RenderSceneWithFBO(g_fboScreen);
    RenderImage(g_fboScreen);
}

シーンの例としては以下,

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28

void RenderScene(void)
{
    static double ang = 0.0;
 
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);
 
    glPushMatrix();
 
    glTranslatef(0.0, 0.0, -4.0);
    glRotatef(ang, 0.0, 1.0, 0.3);
 
        glPushMatrix();
    glColor3d(0.0, 0.0, 1.0);
    glutSolidTeapot(1.0);
    glPopMatrix();
 
    glPopMatrix();
 
    ang = (ang >= 360.0) ? 0.0 : ang+1;
}

上記シーンで描画した結果を以下に示します.

teapot_fbo_1.jpg

添付ファイル: fileteapot_fbo_1.jpg 2495件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-11-30 (水) 13:48:08