Opengl 的片段著色器的Blend的疑惑 片段著色器的Alpha Blend次序?

首先我以前做的都是2d軟渲染

背景:現在開始接觸到Opengl的可編程管線渲染。但是在了解了一點GPU的渲染管線後有一點疑惑!在管線的後面的片段著色器對當前的點輸出顏色後,按照我在2d渲染的經驗是需要和 frame buffer這個像素的點做 alpha blend操作的。

但是:這個地方有一個我有顧慮的地方,比如我要渲染一個模型,那麼這個模型有很多三角形,我一次提交全部的渲染。這個模型有很多三角形組成的,有些三角形在背後有些三角形在前面,這些基元都是並行運算的。按照理解應該是後面的三角形先著色然後顏色寫入frame buffer裡面,然後是前面的三角形著色在後面的frame buffer做alpha blend。但是問題是 這個計算在並行運算過程中並不能保證!有可能前面的基元先計算,在算後面的基元。那麼這樣的結果不就不對了嘛??


GPU能保證按照你提交的三角形的次序進行繪製。

至於空間上誰進誰遠,那GPU是不管的。

所以畫Alpha Blending的時候要對三角形/物體大致排序。

或者使用Depth Peeling這一類的Order Independent Transparency / OIT演算法。


可以認為是無序的

也正因為如此有了那些叫depth peeling的技術


使用AlphaBlend的時候分層繪製,先繪製opaque再繪製transparent,對於transparent物體需要自己排序。

無transparent物體時,使用DepthBuffer(ZBuffer),寫入像素時會寫入z值,近的overwrite遠的discard.


程序好像並不會自動判斷誰在前誰在後。


半透明渲染是個遠古巨坑,因為性質與現在的渲染方法天然不合。

現在的深度剔除是基於z緩衝的,一個片元如果比frame buffer里現有的更近,就渲染並更新z緩衝,否則就直接拋棄。然而半透明的物體能看到被遮擋的東西,直接拋棄就露餡了。不顧z緩衝也依然得不到正確的結果,因為alpha混合顛倒順序會得到不一樣的結果。

一個解決方法是把場景分為有半透明的和不透明的兩部分,先渲染不透明的圖元,然後在主機端對半透明圖元按遠近排序。但這不但代價較高,而且不能解決相互交錯的圖元。

好像有個叫顯卡端片元鏈表的玩意,我沒用過。


額,路過看到這個問題。

其實解決辦法很簡單,先渲染不透明,然後再渲染半透明。

渲染半透明之前,glDepthMask(FALSE) ,將深度緩衝區只讀掉,然後開始渲染半透明,渲染完畢後再 glDepthMask(TRUE) 。

這樣渲染半透明的時候,即使半透明物體在更前面,也不會修改深度緩衝區,最終出來的就是疊加效果。


推薦閱讀:

OpenGL ES 在不同架構上的指令優化是否真的完美?
OpenGL 與 OpenGL ES2 之間有何區別?
請問你用opengl/opengl es做過或者看到過的最酷的作品?
在手機上能否實現Forward+呢?還有其他比較適合手機的多光源演算法嗎?
在攝像機渲染時近大遠小的程度只受物體的深度影響?

TAG:OpenGL | OpenGLES | 計算機圖形學 |