OpenGL基礎33 幀緩衝(上)之離屏渲染

2021-10-23 09:06:09 字數 2169 閱讀 2484

在之前的章節,所有的物體都是中規中矩的顯示的,只考慮了光照對物體的影響,那假設想要顯示特殊的效果該怎麼操作呢?例如馬賽克風、將所有的物體都顯示為黑白色,就像上世紀80年代的灰白電視一樣,又或者說將整個場景渲染到一張泛黃的紙上以體現出年代感……

當然是修改著色器,事實上,很多地方都是這麼做的,不過有些情況下,場景中的物體和對應的著色器都不少,若是想要整個場景(視口)體現出某個效果,就需要借助別的方法了

為了解決這個問題,來學習幀緩衝吧,當有了目的之後才能更好的去理解和掌握。這一章相對之前要複雜一些,但是用一句簡單的話來表達這個過程就是:想辦法把當前的場景作為一張紋理存起來,然後再去全屏渲染這張「紋理」,在這種情況下,我們只需要給這張「紋理」編寫乙個獨一無二的著色器就可以了

到目前為止,已經了解並使用了幾種不同型別的螢幕緩衝:用於寫入顏色值的顏色緩衝,用於寫入深度資訊的深度緩衝,以及允許我們基於一些條件丟棄指定片段的模板緩衝,這幾種緩衝結合起來叫做幀緩衝(framebuffer),它被儲存於記憶體中

我們目前所做的渲染操作都是是在預設的幀緩衝之上進行的,當你建立了你的視窗的時候預設幀緩衝就被建立和配置好了(glfw為我們做了這件事)

是的,glfw已經為我們把這份**寫了,只不過我們是要自己再「客製化」乙個想要的結果,opengl給了我們自己定義幀緩衝的自由,我們可以選擇性的定義自己的顏色緩衝、深度和模板緩衝

和vbo、ebo一樣,也可以用同樣的方法建立和繫結乙個fbo(幀緩衝)變數:

gluint fbo;

glgenframebuffers(1, &fbo);

glbindframebuffer(gl_framebuffer, fbo);

繫結的目標有以下3種,一般都是第一種:

構建乙個完整的幀緩衝必須滿足以下條件:如果不滿足條件,則屬於無效構建

樣本是什麼暫時不管,後面會有講到,總而言之,因為幀緩衝的構建需要條件,所以我們在後面需要用 glcheckframebufferstatus 函式來檢查是否真的滿足所有的條件,如果返回的值是 gl_framebuffer_complete 就說明建立成功了

if (glcheckframebufferstatus(gl_framebuffer) != gl_framebuffer_complete)

cout << "error::framebuffer:: framebuffer is not complete!" << endl;

再回到幀緩衝區,這確實是乙個很重要的概念,它在 opengl基礎1:最簡單的opengl例子 這一章中就被第一次提到了,裡面介紹了 glfwswapbuffers(window) 這乙個函式

而不管是crt,還是液晶,它們都是從緩衝區中讀取資料,其中緩衝區的資料就是通過 cpu 和 gpu 的計算給予的,如果在一幀時間內,cpu 或者 gpu 沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時顯示屏會保留之前的內容不變,這也是介面卡頓的原因

如果理解了雙緩衝區,那麼像理解離屏渲染就容易一些,對於雙緩衝區,需要另外的緩衝區是為了乙個用於顯示的同時,另乙個用於後台繪製,並且相互切換,這樣我們就感覺不到繪製的這一過程。而對於離屏渲染,需要另外的緩衝區是為了二次處理,拿這次緩衝區的資料來為真正要顯示的影象服務,當然啦,這個緩衝區大部分情況下由我們自己建立

在opengl中,gpu有2種渲染方式:

其實,離屏渲染是比較耗得,不止需要建立新的緩衝區,而且還需要多次切換上下文環境,先是從當前螢幕(on-screen)切換到離屏(off-screen);等到離屏渲染結束以後,為了將離屏緩衝區的渲染結果顯示到螢幕上還需要將上下文環境從離屏切換到當前螢幕,除了接下來我們手動建立fbo,以下幾種情況也會觸發離屏渲染:

可能有幾個沒有了解過,這些有機會的話都在後面講,畢竟這也才開始理解離屏渲染

當我們做完所有幀緩衝操作後,不要忘記刪除幀緩衝物件:

gldeleteframebuffers(1, &fbo);
好了,現在回到最初的目的:

想辦法把當前的場景作為一張紋理存起來,然後再去全屏渲染這張「紋理」,在這種情況下,我們只需要給這張「紋理」編寫乙個獨一無二的著色器就可以了

在此,目的就變成了:定義乙個幀緩衝並且啟用,然後走之前正常的渲染邏輯,這個時候,本應該在螢幕中展示的圖象就被渲染到了自己定義的幀緩衝中,接下來,我們再想辦法將幀緩衝中的資料轉變為紋理,並且對這張紋理在預設幀緩衝中進行渲染顯示

OpenGL基礎34 幀緩衝(中)之附件

在之前的章節,所有的物體都是中規中矩的顯示的,只考慮了光照對物體的影響,那假設想要顯示特殊的效果該怎麼操作呢?例如馬賽克風 將所有的物體都顯示為黑白色,就像上世紀80年代的灰白電視一樣,又或者說將整個場景渲染到一張泛黃的紙上以體現出年代感 當然是修改著色器,事實上,很多地方都是這麼做的,不過有些情況...

高階OpenGL渲染管線之幀緩衝(三)

幀緩衝包括之前學的 用於寫入顏色值的顏色緩衝 用於寫入深度資訊的深度緩衝和允許我們根據一些條件對齊特定片段的模板緩衝。他們都儲存在記憶體中,我們也可以定義自己的幀緩衝。在繫結到gl framebuffer目標之後,所有的讀取和寫入幀緩衝的操作將會影響當前繫結的幀緩衝。我們也可以使用gl read f...

OpenGL建立乙個幀緩衝

1.定義幀緩衝變數名 unsigned int gbuffer 2.建立幀緩衝 glgenframebuffers 1,gbuffer 3.將幀緩衝繫結到gl framebuffer glbindframebuffer gl framebuffer,gbuffer 4.將gposition紋理變數儲...