主流的遊戲引擎都是如何解決Alpha Blending問題的呢?

嘗試自己寫DirectX程序的時候碰到了這個問題。

看了這篇文章之後更迷惑了,Depth sorting alpha blended objects

看起來對物體進行排序然後渲染並不是很好的解決方案,那麼主流的遊戲引擎都是如何處理這個問題的呢?

或者說有沒有兼顧性能和效果的解決方案呢?


最近有一些eye trick的方法可以在一定程度不做Alpha Blending。

最近有兩個例子,都是用來渲染毛髮的,毛髮渲染用的Alpha Blending非常多,而這兩個例子中都用了類似的方法避免Alpha Blending的高消耗。

一個是oculus的vr小刺蝟,另一個是Epic本家的Paragon照片級頭髮渲染。

大體思路是在要渲染的頭髮上生成一個隨即噪音場,這個噪音場每一幀都會變化,用噪音作為Mask。

人眼看東西有個奇怪的現象,如果循環看到全透明和不透明的兩個畫面,而且循環的速度足夠快的話,就會覺得看到了半透明的東西。。。

小刺蝟的毛髮就是快速閃爍的Mask,vr的幀數高達90幀,看起來就變成了很柔軟的Alpha Blending感覺。


要像素級排序,也就是OIT。主流引擎很多耗不起這樣的排序,所以很多只是物體排序,錯了就錯了。

至於真的要做OIT的話,常見的套路有:

Depth peeling:慢,費顯存(unbounded),但哪都能用

Stencil routed:費顯存(bounded),D3D10.1+的卡能用

Per-pixel linked lists:略快,沒那麼費顯存,D3D11+的卡能用(細節在實現一個較新的OIT方法:Per-Pixel Linked Lists)

Adaptive transparency:更快,沒那麼費顯存,D3D11+的卡能用(有損)(細節在繼續探索OIT:Adaptive Transparency)

Weighted blended OIT:更快,沒那麼費顯存,D3D11+的卡能用(有損)

Pixel sync:快,不費顯存,D3D12+的卡能用

而如果就是要速度,可以用一個depth peeling的極大簡化版本,只渲染最遠的一層和最近一層。通過設置face culling就能做到,對於幾何不複雜的物體這個近似結果也不錯。


龔大已經說的很詳細了,我補充一點沒有節操的內容:

從工程角度來說,大家都知道透明不好搞,所以盡量不用透明的材質

實在要用的話,首選物體級別到視點距離的排序,如果搞不定再轉向其他方法,例如:

  • 一些基於自身項目特點的變種,例如有的物體使用到視點包圍球的中心的距離,有的物體使用包圍球表面到視點的距離,有的物體還需要加個排序的權重等等

  • 引擎暴露控制繪製順序的方法、介面給client,由client來控制哪些物體先畫哪些後畫。

再遊戲中,其實只要不是特別嚴重的錯誤,透明排序這點問題,錯了也就錯了。當然有的遊戲可能特別看重這個,那麼要麼就上像素級別的排序,要麼就死磕美術。


裝沒看到


畫全部物體的時候,不真正畫trasparent而只是把它們放到bucket裡面,這遍只畫opaque pass。下個pass 用deferred的方法把bucket裡面的transparents全畫一遍。可以在這裡面做簡單排序比如所有標flag1的tans出現在所以標flag2的trans前面。(水面接受點光源的trans在水體本身反射的trans上面)

這個解決方案的核心是 更粗粒度的排序。這樣可以兼顧效率。

---------下面和此題無關

用umbra可以預處理場景做深度排序與此題無關。很多時候由於場景特點等條件限制zprepass不能提升效率。

又想起一個,省stencil一次的方法stencilbuffer不用提前畫出來 在一幀的前半部分用stencilview把這塊buffer從depthstencilbuffer里copy出來,後面在fragmentshader作為srv用。

-----

陰陽師里的aplhabelnd糟糕透了。

透明鬼魂這種對細節要求高的半透可以用zprepass用畫好的深度圖出半透

-----------------下面又和本題有關了

第一段我沒說清楚 再補充下

原本的方法是 用深度排個序 往bucket里放 一個折衷的方法是這樣:

trans的包圍盒拿z出來 做log 按這個值把tans們saturate到總的 不同的buckets裡面(粗粒度的深度排序)。這樣按bucket的index畫的時候實際是粗排序的。在一個bucket內部畫的時候用上文說的flag 還可以再排序 pass0,pass1

---------

還可以再在模型的配置腳本里加zoffset的屬性 給算在哪個bucket裡面的時候作偏移用。用這個offset把特別近在一個bucket里渲染次序變來變去的trans放不同bucket裡面。


推薦閱讀:

計算機視覺和圖像處理方向前景如何?
計算機圖形學的裁剪演算法,實現任意多邊形與直線、圓的裁剪?
256位元組3D程序是如何實現3D引擎的呢?
一個圖形引擎的畫面風格是由那些因素(技術)決定的?
AlphaTest可以在手機上使用嗎?性能是否很差?

TAG:遊戲引擎 | 計算機圖形學 | DirectX |