Pixel Buffer Objectについて PBOとは†Pixel Buffer Object(PBO)はVBOをピクセルデータを格納できるように拡張したものです. PBOではDMAを用いてビデオカードとのデータのやり取りを行うので,CPUサイクルに影響されずに 高速に転送できます.また,フレームバッファやテクスチャメモリとのデータのやり取りも 可能です(glReadPixels, glDrawPixels, glGetTexImage, glTexImage2D, glTexSubImage2Dなどを使用). PBOの使い方†PBOの作成はVBOとほぼ同じです. ただし,glBindBufferなどに指定するtargetに
また,VBOと同様にglMapBuffer, glUnmapBufferを用いてPBOをアプリケーション側のメモリにマッピングすることができます. PBO作成,破棄関数例は以下. /*! * 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を使うこともできますが, ここではテクスチャを使っています. /*! * 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は描画領域と同じ大きさのテクスチャです. 描画時にはシーン描画関数を呼び出した後,上記関数を連続して呼び出します. void Display(void) { RenderScene(); // シーン描画 ProcessImage(); // PBOへの転送と編集 RenderImage(); // 編集したものをテクスチャで描画 } シーンの例として, /*! * シーン描画 */ 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(); } で行った描画結果を以下に示します. |