Framebuffer Object

来源:互联网 发布:windows arp攻击原理 编辑:程序博客网 时间:2024/05/02 08:32
 
很久以前我介紹過OpenGLPixel Buffer,那是一種可以在一張不會被顯示出來的畫布上畫圖的技術(off-screen rendering)。但是此技術已提出很久了,而且非常多限制!第一,它只能在視窗化的系統上使用;第二,Pixel Buffer與原來的Frame Buffer資源完全獨立,實作上會浪費不少空間。另外還有一些使用上不方便的因素。因此OpenGL在2003年提供了一個新的技術放在OpenGL 1.5版內,那就是FBO -- Framebuffer Object

  FBO相當好用!你可以很容易地產生一塊邏輯記憶體來當做Framebuffer使用,而且此buffer包含了color buffer,depth buffer,stencil buffer,也就是你可以在FBO上使用你原本的複雜繪圖演算法。

  當然,Pixel Buffer的特有功能FBO一樣可以達成。你可以把在FBO畫上去的東西當成貼圖,再貼到另一個模型上;也可以在FBO進行非繪圖的數學運算,這都是FBO最常見的應用。

  FBO的使用方法跟Pixel Buffer十分類似,它的使用流程是這樣:設定好OpenGL的基本環境、建立FBO、啟動FBO、對FBO繪圖、將FBO當成貼圖、啟動原來的Frame Buffer、對Frame Buffer畫圖、解除貼圖的連結、刪除FBO。

1. 設定OpenGL的基本環境:請參考我之前的文章 -- "在VC++ .NET framework 使用OpenGL"及”OpenGL in VC++ .NET 2005”,這邊不多介紹。這個步驟主要是取得HDC及HGLRC。

2. 建立、啟動、關閉FBO

  這裡會用到一個OpenGL extension API:

        glGenFramebuffersEXT(n, &nFboID);

        這個API用法跟glGenTextures一樣,它可以在Video ram上配置n個FBO。接下來,我們就可以啟用FBO,這時需要這個OpenGL extension API:

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, nFboID);

  這裡有很重要的一點,只要想對FBO進行任何設定,包括下面將繼續介紹的初始設定,你都必須用上述API來啟動它。至於關閉FBO,只要nFboID給0就好:  

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

然後,因為FBO都會當成貼圖來使用,所以你也必須為FBO配置一個貼圖空間給它:

        glGenTextures(1, &nTexID);
        glBindTexture(GL_TEXTURE_2D, nTexID );
        glTexImage2D(GL_TEXTURE_2D, 0, nInterFmt, nWidth, nHeight, 0, GL_RGBA, GL_FLOAT, NULL);

  注意!FBO只是個像記憶體管理者的東西,它不是一塊很大的記憶體。你必須在建立FBO後,把color buffer或depth buffer繫結(binding)在FBO上。這裡會用到此OpenGL Extension API:

        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, nAttach, GL_TEXTURE_2D, nTexID , 0);

  其中nAttach是你附著哪種buffer給FBO的貼圖空間。你可以設的buffer有          
                GL_COLOR_ATTACHMENT0_EXT ~ GL_COLOR_ATTACHMENT3_EXT

    為什 我只列四個?因為一般市面上的新台幣一萬元以下的顯示卡只有四的color buffer讓你使用。但半年後會是什 樣的情況,就不得而知了。

        (2) Depth buffer: GL_DEPTH_ATTACHMENT_EXT

        (3) Stencil buffer: GL_STENCIL_ATTACHMENT_EXT

3. 對FBO繪圖:繪圖前要做一件很重要的事,你必須告訴OpenGL現在是對哪個buffer在繪圖及讀取:

        glDrawBuffer(nAttach);
        glReadBuffer(nAttach);

  接下就照你平常繪圖的方式。有一點需要特別注意,就是在FBO的繪圖環境是與原來的Frame Buffer是共享的,跟Pixel Buffer不一樣。也就是說投影矩陣、幾何資訊、光源、貼圖...等,都是相同的!  

        完成繪圖後,除了關閉FBO外,還需記得切換成回原來的frame buffer(一般是GL_COLOR_ATTACHMENT0_EXT ):

        glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT );
        glReadBuffer(GL_COLOR_ATTACHMENT0_EXT );

6. 將FBO當成貼圖:記得一開始我們為FBO配置的一個貼圖代號嗎?就利用此代號進行你一般貼圖的動作:

        glBindTexture (GL_TEXTURE_2D, nTexID);

        glEnable(GL_TEXTURE_2D);

7. 刪除FBO

glDeleteTextures(1, &nTexID);
                glDeleteFramebuffersEXT (1, &nFboID);

  以上就是FBO的使用方式。FBO目前最常的應用就是用在GPGPU上(General Purpose GPU, 繪圖晶片泛用運算)。我們可以用市面上的3D顯示卡上的圖型處理器(Graphics Processing Unit, GPU)來跑程式,下圖就是我用GPU來進行傅立葉轉換(Fourier Transform),速度真的很快!下次我將為各位介紹什 是GPGPU。

 

參考資料:

[1] Simon Green, "The OpenGL Framebuffer Object Extension", NVIDIA Corporation.