Early Depth Test + Forward 和 Deferred Rendering 比較?
Early Depth Test 和 Deferred Rendering 都能保證不會重複渲染某個像素
但是Deferred Rendering要渲染一個GBuffer(GBuffer的本質不就是把頂點輸出屬性的光柵化插值結果直接(比如光柵化插值後的Normal)或間接(比如用光柵化插值後的UV採樣紋理後的顏色值)的緩存到一個Buffer中么,可這有必要緩存下來么,感覺是多此一舉)
而Early Depth Test只是在光柵化階段提前插值深度和比較深度 未通過深度測試的像素的其餘頂點屬性也不會插值 像素也不會進入片段著色器 也不會寫入到Framebuffer中
這麼看來Early Depth Test在性能和帶寬以及存儲空間上都有明顯優勢啊
並且我認為Early Depth Test + Forward還有以下優勢:
1.Early Depth Test + Forward幾乎對程序員是透明的
Deferred Rendering實現起來相對複雜的多
2.Early Depth Test + Forward只要Framebuffer支持多重採樣格式就天然支持多重採樣啊(一般窗口系統都提供了這樣的Framebuffer格式)
Deferred Rendering卻需要FBO的所有Attachment組件都支持多重採樣格式才行,而多重採樣紋理在新版本OpenGL中才被包含在Core Profile中吧
感覺Deferred Rendering去緩存GBuffer的思路根本是錯的啊
是我理解有誤么?
問題主應該說的是 depth prepass (early depth pass) + forward,可能把 early depth pass 和 early depth test 混淆了。
分別說一下兩種的優缺點,然後各取所需吧。不過首先說明的是兩種方法都對半透物體沒轍:
Depth pre-pass + forward:
PRO:
1. 保證 shading 時僅處理可見的像素;
2. 對於 pixel kill 的像素(discard / clip 的像素無法使用硬體自動 early depth test,DX11 下可以用 [earlydepthstencil] 強制開啟),其 pixel shader 開銷被 depth pre-pass 的廉價 pixel shader 代替;
3. 支持傳統 MSAA;
4. 無需絞盡腦汁把材質所需信息擠進 GBUFFER,可以輕鬆應對所需材質種類較多的項目(比如需要多種各項異性材質的場景)。
CON:
1. 兩遍 draw call,CPU 佔用大;
2. 如果要處理多光源:
(1)傳統的 forward lighting (幾個光源就是幾個 forward pass)需要更多的 draw call,效率極低;
(2)tiled forward / forward +,在 DX9 下會由於 PS 寄存器不夠而編譯不過。在 DX11 下會由於佔用大量 VGPR 而降低 PS 效率。
3. image based lighting 實現起來也很困難。reflection capture 本質上就是光源,對於多個 reflection capture 疊加的場景用 forward 方法去實現,還是繞不過上邊兩點。
4. 對於需要場景信息的特效,比如 AO 需要 depth buffer 和 normal buffer,比如 SSR 需要 depth buffer, normal buffer, specular buffer, roughness buffer 等等,實現起來會很困難。
-------------------------------------------------------------------------------------------
Deferred shanding:
PRO:
1. 依然保證僅 shading 可見的像素;
2. 一遍 draw call (Gbuffer Pass)搞定;
3. image based lighting 和 多光源渲染 實現簡單;
4. Gbuffer 可以用於大量特效,比如AO,SSR等。
CON:
1. Gbuffer Pass 自身就是一個 forward pass,如果 Gbuffer shader 複雜,那麼是否會有 overdraw 的問題?是否需要 early depth pass? 即使 Gbuffer Pass 中材質是根據遠近距離排序過的,對於有 pixel kill 的材質,其 overdraw 的消耗還是很大。
2. MSAA 實現起來極其蛋痛(但是現在 TXAA 或者某些顯卡上的 EQAA 效果不比 MSAA 差)。
3. 如果想省帶寬,就需要絞盡腦汁把材質信息塞到 Gbuffer 內,很折騰。
4. deferred shading 僅實現一種 BRDF(一般是各向同性的),有的項目把各項同性 BRDF 的各向異性版本也弄在裡面。但是如果各向異性材質種類很多,還是逃不了要用 forward shanding 來實現。
===================================================
補充幾點:
DOOM 採用的是 forward shading + 部分 deferred lighting 的方法(注意其順序是反的),forward shading pass 實現直接光照,同時輸出 normal buffer 和 specular buffer,然後在用後面的 deferred lighting 補充 AO 和環境反射。這個算是解決了「Depth pre-pass + forward」 中的第三個和第四個問題。
隨著 DX12 Vulkan 的出現,很多廠商開始嘗試:什麼是deferred material shading?是否會在未來流行開來?
===================================================
對,你的理解有誤。
Deferred Rendering不但能保證不會重複渲染某個像素,還能保證畫物體的次數是常量(O(1))。Forward沒法保證這一點,光源多就得把物體多畫幾次(O(N))。這才是最大的區別。
1)Deferred Shading把幾何計算 (如位置坐標和法向量的變換)跟lighting分開成兩個Pass,其中lighting是計算的重頭,特別是有多個光源的情況。複雜場景的深度層次會比較多,那些較遠的,並且被送進Pixel Shader的像素的lighting就造成計算浪費。
第一個Pass最終在GBuffer留下來的都是最近的像素,到了第二個Pass的lighting就只剩一次了,GBuffer是有用的啊…
2)Early Z test是硬體實現的,但要盡量把靠前的物體先畫才能大程度減少lighting的浪費,最極端情況下,對於從遠到近做rendering,Early Z test是沒起效果的
1. Early Depth Test + Forward kill
這是GPU硬體的一個特性,對開發者來說是透明的。其原理就是根據深度值將被遮擋的pixel剔除掉,減少調用PS的次數,從而達到提高效率降功耗的目的。
2. Deferred Rendering
這可以理解是一種軟體演算法,需要開發者自己實現。其基本原理就是將原來的PS分成兩個pass.
第一個pass, 將所有position, color, normalize cood, 等相應的pixel內插值分別保存在獨立的texture中。這裡要用到MRT特性, 即創建一個新的fragment buffer(就是所謂的gBuffer),將一個或多個texture attach上去作為color attachment。
第二個pass, 根據前一個pass產生的深度值計算光照關係,再將上述texture bind上,最後在一個新的光照PS中確定每個像素的顏色。
Early Z不能保證剔除所有不可見像素啊……如果要像延遲渲染那樣保證每個像素只做一次lighting就需要depth pre-pass,那樣開銷就上去了。另外保存一個gbuffer也有其他好處,例如屏幕空間渲染,減少VGPR壓力。
你第二段開頭的描述,關於Gbuffer那裡,可以看出你把deferred shading和pvr的deferred rendering搞混了,兩個不是一件事情。gbuffer那個deferred shading,在pvr晶元上仍然會被deferred ,在其它晶元上仍然會被early z
推薦閱讀:
※渲染的時候是不是頂點數目越少越好?
※計算機圖形學中,面的最小基本單位為什麼一般是三角形?
※unity 最後一次drawcall 如何避免?
※請教各位在pc上使用webgl以及opengl渲染yuv數據的性能問題,有何改進方向?