OpenGL中FBO的概念及其應用

FBO一個最多見的應用就是:渲染到紋理(render to texture),經過這項技術能夠實現發光效果,環境映射,陰影映射等很炫的效果。

OpenGL中的Frame Buffer Object(FBO)擴展,被推薦用於把數據渲染到紋理對像。相對於其它同類技術,如數據拷貝或交換緩衝區等,使用FBO技術會更高效而且更容易實現。

在OpenGL渲染管線中,幾何數據和紋理最終都是以2d像素繪製到屏幕上。最後一步的渲染目標在OpenGL渲染管線中被稱爲幀緩存(frame buffer)。幀緩存是顏色緩存、深度緩存、模板緩存、累積緩存的集合。默認狀況下, OpenGL使用的幀緩存是由窗體系統建立和管理的。

在OpenGL擴展中,GL_EXT_framebuffer_object擴展提供了一個建立額外幀緩存對象(FBO)的接口。這個幀緩存的建立和控制徹底是由OpenGL完成的,有別於窗體系統建立的默認的幀緩存。與系統默認的幀緩存相似,一個FBO也是顏色緩存、深度緩存、模板緩存的集合(FBO不包括累積緩存),而後OpenGL程序就能夠把渲染重定向到FBO中。

這裏有一個新的概念須要注意,那就是renderbuffer object。這個對象是經過GL_EXT_framebuffer_object擴展建立。它被用來在渲染過程當中爲一個2D圖像提供渲染目標。

下圖展現了FBO和renderbuffer object與texture object之間的關係。從圖中咱們能夠看出:多個renderbuffer object和texture object能夠經過掛接點掛接到FBO上。須要主要的是FBO並無實際存儲數據的地方,它只是一個數據的殼,它只有掛接點。



一個FBO對象包含多個顏色掛接點和一個深度掛接點以及一個模板掛接點。不一樣的顯卡支持的顏色掛接點的數目是不一樣的,能夠經過查詢GL_MAX_COLOR_ATTACHMENTS_EXT獲取支持的最大的掛接點的數目。支持多個顏色掛接點的緣由是FBO能夠在同一時間內將顏色緩存渲染到多個目標中去,這種能力被稱爲MRT(multiple render targets)。經過GL_ARB_draw_buffers擴展能夠實現該功能。

幀緩衝提供了一種有效的切換機制,使得掛接和卸載一個可掛接的圖像很是之迅速。FBO使用glFramebufferTexture2DEXT()來進行texturebuffer對象的切換,使用glFramebufferRenderbufferEXT()來進行renderbuffer對象的切換。

讓咱們看一下其使用過程:
1.FBO對象的建立與銷燬
void glGenFramebuffersEXT(GLsizei n, GLuint* ids);
void glDeleteFramebuffersEXT(GLsizei n, const GLuint* ids);
第一個參數是要建立的FBO的個數,第二個保存建立的FBO的ID。

2.一旦FBO對象建立完畢,即要進行綁定
void glBindFramebufferEXT(GLenum target, GLuint id);
第一個參數必須是GL_FRAMEBUFFER_EXT
第二個參數是第一步建立FBO對象中獲取的id號,該id號是一個非0值,由於系統默認的FBO的id號是0,因此若是你想取消FBO的綁定,將id等於0做爲id參數傳遞給該函數便可。

3.建立Renderbuffer Object
void glGenRenderbuffersEXT(GLsizei n, GLuint* ids);
void glDeleteRenderbuffersEXT(GLsizei n, const GLuint* ids);

4.一樣的,Renderbuffer Object建立好以後,要記得綁定。
void glBindRenderbufferEXT(GLenum target, GLuint id)

5.肯定Renderbuffer Object的數據格式和尺寸。
  這一步很重要,由於咱們只是建立了Renderbuffer Object,尚未爲它提供一個存儲數據的地方,也沒有指定其存儲數據的地方存儲什麼格式的數據,因此接下來就要作這個事情了。
void glRenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
第一個參數必須是GL_RENDERBUFFER_EXT
第二個參數能夠是可渲染的顏色格式,如(GL_RGB, GL_RGBA, etc.),可渲染的深度格式(GL_DEPTH_COMPONENT)或者是可渲染的模板格式(GL_STENCIL_INDEX)。
最後兩個參數就是以像素爲單位指定數據所要佔用內存的大小。

這裏須要注意兩點:
1。 指定的內存區域的寬和高應該都小於GL_MAX_RENDERBUFFER_SIZE_EXT,不然將產生GL_INVALID_VALUE錯誤。
2。 全部的texture object也好,renderbuffer object也好,其寬和高都是嚴格一致的。

6.指定掛接的對象
glFramebufferTexture2DEXT函數掛接一個texture圖像到FBO
glFramebufferRenderbufferEXT函數掛接一個Renderbuffer圖像到FBO

7.檢測FBO狀態
該掛接的對象都掛接好了,在使用FBO以前,必需要檢查FBO的狀態是否處於完成狀態。若是FBO處於未完成狀態,那麼繪製操做就會失敗。如何獲取FBO的完成狀態呢?使用
glCheckFramebufferStatusEXT函數。

至此,關於FBO的概念及其使用就算告一段落了。下面給出一個完整的例子,該例子是從國外一個網站上找到的,代碼寫得簡單而漂亮,對FBO的演示也很完善。緩存

FBO Demo函數

相關文章
相關標籤/搜索