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

2021-07-13 03:24:05 字數 3745 閱讀 2208

概要

在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掛接的二維陣列物件的長度和寬度必須不能為0。

如果乙個二維陣列物件被掛接到fbo的顏色緩衝區掛接點時,二維陣列必須具有內部顏色格式(gl_rgba, gl_depth_component, gl_luminance等)。

如果乙個二維陣列物件被掛接到fbo的深度緩衝區掛接點時,二維陣列必須具有內部深度格式(gl_depth_component, gl_depth_component24_ext等)。

如果乙個二維陣列物件被掛接到fbo的模板緩衝區掛接點時,二維陣列必須具有內部模板格式(gl_stencil_index, gl_stencil_index8_ext等)。

fbo至少掛接有乙個二維陣列緩衝區物件。

同乙個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渲染目標 渲染到紋理 技術,本質上來說就是一次對場景中幾何體的渲染過程。它本身要花費一些執行時間,進而導致幀速的下降。當你渲染複雜耗時的內容的時候,你不得不考慮相...