导读:
很久以前我介紹過OpenGL的Pixel 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_BACK):
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
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 Computation on GPUs, 繪圖晶片泛用運算)。我們可以用市面上的3D顯示卡上的圖型處理器(Graphics Processing Unit, GPU)來跑 程式,下圖就是我用GPU來進行傅立葉轉換(Fourier Transform),速度真的很快!下次我將為各位介紹什麼是GPGPU。
參考資料:
[1] Simon Green, "The OpenGL Framebuffer Object Extension", NVIDIA Corporation.
本文转自
http://www.wretch.cc/blog/glCheng/4638938

很久以前我介紹過OpenGL的Pixel 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_BACK):
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
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 Computation on GPUs, 繪圖晶片泛用運算)。我們可以用市面上的3D顯示卡上的圖型處理器(Graphics Processing Unit, GPU)來跑 程式,下圖就是我用GPU來進行傅立葉轉換(Fourier Transform),速度真的很快!下次我將為各位介紹什麼是GPGPU。

參考資料:
[1] Simon Green, "The OpenGL Framebuffer Object Extension", NVIDIA Corporation.
本文转自
http://www.wretch.cc/blog/glCheng/4638938