半透物體的實時渲染是一件讓游戲開發者很頭疼的事情,如下圖所吐槽。需要排序,一旦出現geometry交叉的情況,半透計算還必出錯。
這幾天從理論到實踐地研究了下所謂的OIT技術,對半透問題有了一定的了解,現作個記錄。
最簡單的OIT方法是Nvidia 2001年的那篇老paper(“Interactive order-independent transparency ”)介紹的depth-peeling。真的是很簡單的方法,因為連我都看得懂!核心算法如下:
看得出來,每個半透物體需要多個pass渲染,每個pass剝離一層最近深度,同時該方法需要2個depth buffer的協作。如果用D3D或opengl來實踐的話,必然比較麻煩,你會發現原paper一共10頁,大部分是在講怎么用opengl的trick來表達出算法。所以我在自己的soft renderer中進行了實踐,事實證明真是簡單的一逼,軟渲就是靈活自由,絕對是預研的正確選擇。
下面是實踐的過程。測試場景是2個半透的雙面的交叉的teapot~
-
Solid View
這是非半透渲染方式,提供遮擋關系供半透渲染時參考。可以得出我們期望的正確結果是,左邊圈中部分應該是綠里透紅,右邊圈中部分應該是紅里透綠。。
-
Normal Transparency
這是普通的半透渲染。可以看到,綠茶壺的茶柄是綠里透紅,看上去像是該部分在紅茶壺的前面,這是不正確的。
-
OIT with 4 layers
這是4層depth peeling的結果。注意觀察綠茶壺的茶柄部分是紅里透綠,像是處在紅茶壺的內部,這才是正確的。
ps:唉,我的軟渲光柵化還是有問題,那些點線。。暫時解決不了,真頭疼,不要在意那些細節。。
再看個例子,sponza場景的花壇,它整體是一個模型。
下圖左邊是max中實時渲染的,右邊是render出來的,不管是ray trace還是depth peel,肯定是准確的。
下面是我軟渲中的對比(考眼力,看輪廓,一致的才對):
接下來有空研究下那個什么per-pixel linked list OIT和DXSDK sample中的硬件實現方式。