Opengl中的FBO物件

2021-07-25 11:14:18 字數 3453 閱讀 7939

文章**:

概要

在opengl的渲染管線中,幾何資料和紋理通過一系列變換和測試,最終被渲染成螢幕上的二維畫素。那些用於儲存顏色值和測試結果的二維陣列的幾何被稱為幀緩衝區(frame buffer)。這些二維陣列按用途劃分,可分為顏色緩衝區(color buffer),深度緩衝區(depth buffer),模版緩衝區(stencil buffer)和累加緩衝區(accumulation buffer)。當我們建立了乙個可供opengl繪製用的窗體後,窗體系統會為我們生成乙個預設的幀緩衝區,這個幀緩衝區完全是由窗體系統來管理的,且僅用於將渲染後的影象輸出到視窗的顯示區域。

然而,我們可以使用opengl提供的gl_ext_framebuffer_object擴充套件功能來建立額外的幀緩衝區。gl_ext_framebuffer_object擴充套件功能中,提出了幀緩衝區物件(framebuffer object,縮寫為fbo,下文中將使用fbo來代表幀緩衝區物件)的概念,用於對幀緩衝區進行建模。這樣一來,無論是窗體系統建立的幀緩衝區,還是用於屏外渲染的幀緩衝區,都是fbo的例項。有了fbo,程式設計師就可以重定向渲染目標到其他的儲存空間,比如將渲染目標重定向到紋理空間,實現渲染到紋理功能(render to texture)。

上文提到過幀緩衝區中包含的二維陣列按用途劃分,可分為顏色緩衝區(color buffer),深度緩衝區(depth buffer),模版緩衝區(stencil buffer)和累加緩衝區(accumulation buffer)。fbo中也提供了與顏色緩衝區、深度緩衝區和模版緩衝區相對應的功能(注意,fbo沒有提供與累加緩衝區對應的功能)。但是,這並不意味著fbo會直接為這些緩衝區分配空間。fbo只是為這些緩衝區提供乙個或多個掛接點。我們需要分別為各個緩衝區建立物件,申請空間,然後掛接到相應的掛接點上。fbo提供的掛接點如下圖所示。

可以看出,fbo提供了多個顏色緩衝區掛接點gl_color_attachment0_ext ... gl_color_attachmentn_ext、乙個深度緩衝區掛接點gl_depth_attachment_ext和乙個模板緩衝區掛接點gl_stencil_attachment_ext。顏色緩衝區掛接點的個數是因不同廠商和不同型號的顯示卡而異的。你可以通過gl_max_color_attachments_ext查詢當前顯示卡所支援的顏色緩衝區掛接點的最大個數。fbo提供多個顏色緩衝區掛接點的用意是,允許程式設計師進行多目標渲染(使用gl_arb_draw_buffers擴充套件功能)。

能夠與fbo掛接的物件有兩種,一種是紋理物件(texture object),另一種是渲染緩衝區物件(renderbuffer object)。紋理物件,就是我們平日為模型設定紋理貼圖時使用的物件;而渲染緩衝區物件可以用作不具有紋理格式的緩衝區,如深度緩衝區和模板緩衝區。當然,渲染緩衝區物件也可以用來渲染場景。

前面提到過,窗體系統建立的幀緩衝區也有對應的fbo的例項。但是,這個fbo與其他通過手工建立的fbo相比有許多不同。第一,通過手工建立的fbo不能用於將渲染結果直接顯示到視窗輸出區,通過手工建立的fbo只能用於屏外渲染(off-screen rendering);第二,窗體系統生成的fbo在建立的時候就擁有顏色緩衝區,深度緩衝區,模版緩衝區,且建立後就為這些緩衝區分配了空間。而手工建立的fbo需要手動為其新增各個緩衝區,並為其申請空間。窗體系統建立的fbo中的各個緩衝區物件不能與手動建立的fbo的掛接點掛接,反之亦然。

建立、繫結和刪除乙個fbo

我們可以使用glgenframebuffer***t()來向opengl申請乙個或者多個閒置的fbo的id。注意,就算成功地申請到了閒置的id,opengl也不會馬上為其建立例項。只用當呼叫glbindframebufferext ()繫結fbo的時候opengl才會真正的建立乙個fbo例項(這和其他glbind*函式極為相似)。在fbo被繫結之後,這個fbo就會被opengl當作當前的操作物件,後續的操作都被視為對被繫結的fbo進行的操作。窗體系統建立的fbo的id預設為0。我們可以通過呼叫gldeleteframebuffer***t()函式來釋放fbo的例項,如果要刪除的fbo例項正在被使用,則opengl會自動繫結視窗系統建立的fbo(id為0)。

渲染緩衝區物件

fbo建立完成後,還不能對其進行什麼實質性的操作。因為,fbo的各個掛接點上還沒有掛接實際的儲存物件。我們需要手動建立這些物件,並將其與既存的fbo物件進行掛接。上文提到過,能夠與fbo掛接的物件有兩種,一種是紋理物件(texture object),另一種是渲染緩衝區物件(renderbuffer object)。讀者可能對紋理物件比較熟悉,因為在為模型進行紋理貼圖的時候,經常要使用這種物件。然而,對於渲染緩衝物件,讀者可能會不太熟悉,因為這是opengl擴充套件中新引入的功能。下文將著重介紹渲染緩衝區物件的內容。

渲染緩衝區物件主要是為了實現屏外渲染(off-screen rendering)而設計的。渲染緩衝區物件主要用做fbo的深度緩衝區和模板緩衝區。可以使用glgenrenderbuffer***t()函式來申請乙個或多個閒置的渲染緩衝區物件id(非負整數)。id 0被opengl所保留。注意,申請了閒置id之後,opengl並沒有建立實際的物件,需要呼叫glbindrenderbufferext()函式來繫結並建立實際的物件。如果繫結id 0,opengl會解除先前設定的渲染緩衝區物件。

上文提到過,渲染緩衝區物件實際上是某種二維陣列的抽象。在繫結了乙個渲染緩衝區物件之後,需要使用glrenderbufferstorage()函式為其分配二維陣列儲存空間。注意,同乙個fbo中的各個二維陣列空間的行數(或列數)應該相同。

同fbo類似,可以使用gldeleterenderbuffer***t()函式來刪除乙個渲染緩衝區物件。

掛接

可以使用glframebufferrenderbufferext()函式將渲染緩衝區物件掛接到fbo上;使用glframebuffertexture2d()。如果掛接的id為0,則opengl將解除先前的繫結。當被繫結紋理物件或渲染緩衝區物件被刪除,則他們會被自動從當前正在使用的fbo上解除掛接。如果紋理物件或渲染緩衝區物件被掛接到多個fbo上,他們被刪除的時候,只會從當前被繫結的fbo上解除掛接,而不會從未被繫結的fbo上解除繫結。

fbo的完整性

在向fbo輸出渲染結果之前,需要測試fbo的完整性。如果fbo不完整,任何渲染操作都會失敗。我們可以使用glcheckframebufferstatu***t()函式來測試fbo的完整性(此函式不能在glbegin()和glend()函式之間呼叫)。fbo完整性的判別法則如下:

fbo的使用

當所有上述的準備工作都完成之後,就可以呼叫glbindframebufferext()來繫結乙個fbo。隨後,就可一像操作窗體系統提供的幀緩衝區一樣操作當前繫結的fbo了。日常的3d渲染操作這裡不再贅述。這裡主要強調畫素操作的使用。opengl提供了glblitframebufferext()函式進行畫素操作。

OpenGL中的FBO物件(含原始碼)

概要 在opengl的渲染管線中,幾何資料和紋理通過一系列變換和測試,最終被渲染成螢幕上的二維畫素。那些用於儲存顏色值和測試結果的二維陣列的幾何被稱為幀緩衝區 frame buffer 這些二維陣列按用途劃分,可分為顏色緩衝區 color buffer 深度緩衝區 depth buffer 模版緩衝...

OpenGL緩衝區物件之FBO

在opengl渲染管線中幾何資料和紋理經過變換和一些測試處理,最終會被展示到螢幕上。opengl渲染管線的最終位置是在幀緩衝區中。幀緩衝區是一系列二維的畫素儲存陣列,包括了顏色緩衝區 深度緩衝區 模板緩衝區以及累積緩衝區。預設情況下opengl使用的是視窗系統提供的幀緩衝區。opengl的gl ar...

Opengl中的FBO渲染到紋理

渲染到紋理用途 遊戲中水的倒影,汽車的反光鏡,gpgpu必備。實現參見紅皮書的 至於ogre中的渲染到紋理可以參考翻譯文件第八章 ogre渲染目標 渲染到紋理 技術,本質上來說就是一次對場景中幾何體的渲染過程。它本身要花費一些執行時間,進而導致幀速的下降。當你渲染複雜耗時的內容的時候,你不得不考慮相...