Pixel Buffer Objectについて

PBOとは

Pixel Buffer Object(PBO)はVBOをピクセルデータを格納できるように拡張したものです. PBOではDMAを用いてビデオカードとのデータのやり取りを行うので,CPUサイクルに影響されずに 高速に転送できます.また,フレームバッファやテクスチャメモリとのデータのやり取りも 可能です(glReadPixels, glDrawPixels, glGetTexImage, glTexImage2D, glTexSubImage2Dなどを使用).

PBOの使い方

PBOの作成はVBOとほぼ同じです. ただし,glBindBufferなどに指定するtargetに

  • GL_PIXEL_PACK_BUFFER : ピクセルデータをPBOへ転送(glReadPixel, glGetTexImage)
  • GL_PIXEL_UNPACK_BUFFER : PBOからピクセルデータを取得(glDrawPixels, glTexImage2D, glTexSubImage2D) を指定します. 例えば,フレームバッファとのデータのやり取りならば,
  • OpenGLフレームバッファ -> PBO : GL_PIXEL_PACK_BUFFERを指定して,glReadPixelsを実行
  • PBO -> OpenGLフレームバッファ : GL_PIXEL_UNPACK_BUFFERを指定して,glDrawPixelsを実行

また,VBOと同様にglMapBuffer, glUnmapBufferを用いてPBOをアプリケーション側のメモリにマッピングすることができます.

PBO作成,破棄関数例は以下.

  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
/*!
 * PBOの作成
 * @param[out] pbo 名前
 * @param[in] w,h,c 幅,高さ,チャンネル数
 */
void CreatePBO(GLuint &pbo, int w, int h, int c = 3)
{
    // PBO作成とバインド
    glGenBuffers(1, &pbo);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
 
    glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, w*h*c, 0, GL_DYNAMIC_DRAW);    // バッファの作成と初期化
 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
 
/*!
 * PBOの削除
 * @param[inout] pbo 名前
 */
void DeletePBO(GLuint &pbo)
{
    glBindBuffer(GL_ARRAY_BUFFER, pbo);
    glDeleteBuffers(1, &pbo);
    pbo = 0;
}

PBO使用例

PBOの使用例として,フレームバッファに描画したものをPBOに読み込み, グレイスケール化後再描画を行うものを示します. 再描画にはglDrawPixelsを使うこともできますが, ここではテクスチャを使っています.

  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
/*!
 * PBOによる画像処理
 */
void ProcessImage(void)
{
    // フレームバッファの内容をPBOに転送
    glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, g_iPBOSrc);    // PBOをアクティブにする
    glReadPixels(0, 0, g_iWinW, g_iWinH, GL_BGRA, GL_UNSIGNED_BYTE, 0);     // 描画をPBOにロード
 
    // PBOの内容を編集
    GLubyte *ptr = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_WRITE);
    if(ptr){
        for(int i = 0; i < g_iWinW*g_iWinH; ++i){
            GLubyte gray = (GLubyte)((ptr[4*i]+ptr[4*i+1]+ptr[4*i+2])/3.0);
            ptr[4*i]   = gray;
            ptr[4*i+1] = gray;
            ptr[4*i+2] = gray;
        }
        glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
    }
    glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
 
    // PBOからテクスチャへ転送
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, g_iPBOSrc);
 
    glBindTexture(GL_TEXTURE_2D, g_iTexScreen);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_iWinW, g_iWinH, GL_BGRA, GL_UNSIGNED_BYTE, 0);
 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
 
/*!
 * 画像の描画
 */
void RenderImage(void)
{
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
 
    glMatrixMode( GL_MODELVIEW);
    glLoadIdentity();
 
    glViewport(0, 0, g_iWinW, g_iWinH);
    
    glBindTexture(GL_TEXTURE_2D, g_iTexScreen);
 
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 1.0);    glVertex3f(-1.0,  1.0, 0.5);
    glTexCoord2f(1.0, 1.0);    glVertex3f( 1.0,  1.0, 0.5);
    glTexCoord2f(1.0, 0.0);    glVertex3f( 1.0, -1.0, 0.5);
    glTexCoord2f(0.0, 0.0);    glVertex3f(-1.0, -1.0, 0.5);
    glEnd();
 
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
 
    glDisable(GL_TEXTURE_2D);
 
    glutSwapBuffers();
}

g_iWinW,g_iWinHは描画領域の大きさで,g_iTexScreenは描画領域と同じ大きさのテクスチャです. 描画時にはシーン描画関数を呼び出した後,上記関数を連続して呼び出します.

  1
  2
  3
  4
  5
  6
void Display(void)
{
    RenderScene();    // シーン描画
    ProcessImage();    // PBOへの転送と編集
    RenderImage();    // 編集したものをテクスチャで描画
}

シーンの例として,

  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
/*!
 * シーン描画
 */
void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glPushMatrix();
    
    g_tbView.TrackballApply();    // マウスによる回転・平行移動の適用
 
    // 図形の描画
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);
 
    glPushMatrix();
    glColor3f(0.0, 0.0, 1.0);
    glutSolidTeapot(1.0);
    glPopMatrix();
 
    glPopMatrix();
 
    glFlush();
}

で行った描画結果を以下に示します.

teapot_gray_1.jpg

添付ファイル: fileteapot_gray_1.jpg 1535件 [詳細] fileteapot_gray.jpg 799件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-10-27 (木) 15:09:15 (3259d)