Deferred Rendering

導(dǎo)言

最早為大眾知曉并接受的渲染框架或者說渲染模式是前向渲染(Forward Rendering)。前向渲染埃仪,用一句話來概括必盖,就是對于場景中的每個物件,都進(jìn)行一次渲染饵隙,而在這一次渲染中撮珠,需要對場景中的所的光源都處理一遍(這種處理可以放在一個Shader中完成,也可以放在多個shader中完成金矛,當(dāng)放置在多個shader中完成時芯急,就需要經(jīng)過多個pass才能將所有的shader都運(yùn)行一遍,而這種方式的成本會比較高驶俊,所以對于前向渲染而言娶耍,通常都是直接使用一個shader完成所有光源的計(jì)算處理),并將多個光源的處理結(jié)果融合起來作為最終的結(jié)果輸出到屏幕上饼酿。

前向渲染的缺點(diǎn)主要有以下幾個榕酒,

  • 不管光源是否會有光線投射到物體上,都要對這個光源進(jìn)行一次處理故俐,對于無法照射到這些物體上的光源而言想鹰,這會造成極大浪費(fèi)
  • 不同種類的光源的處理方式是不同的,其shader的計(jì)算過程也是不同的药版,當(dāng)所有光源的處理都放在一個shader中的話辑舷,就會需要走不同的分支,而實(shí)際上在shader的執(zhí)行過程中槽片,分支的意思就是所有的分支都要執(zhí)行何缓,最終選擇一條分支的輸出做為輸出肢础,也是另一個存在浪費(fèi)的地方
  • 如果所有光源的處理都放在一個shader中執(zhí)行,那么各個光源相關(guān)的數(shù)據(jù)都會是一直放在內(nèi)存中備用的碌廓,比如各個光源的shadow map等在需要計(jì)算實(shí)時陰影的時候传轰,就需要一直保持在內(nèi)存中,這種情況會導(dǎo)致可用顯存變得緊張谷婆。
  • 當(dāng)光源數(shù)目過于龐大的時候慨蛙,這時候寄存器的數(shù)目會變得不夠用,從而不得不將一個pass的處理分割成多個pass 完成波材,而分割又進(jìn)一步加劇了時間的消耗股淡。
  • 對于由多個小尺寸的三角形面片組成的物體而言,某個像素可能同時被多個三角面片覆蓋廷区,導(dǎo)致需要進(jìn)行多次ps計(jì)算唯灵,這也會導(dǎo)致進(jìn)一步的浪費(fèi)。
  • 對于層次復(fù)雜的場景隙轻,某個像素點(diǎn)可能對應(yīng)多個重疊的物件埠帕,在渲染的時候,所有的物件都需要進(jìn)行一次渲染玖绿,但只有最接近相機(jī)位置的物件的渲染結(jié)果是有效的(此處只討論不透明物件)敛瓷,這種現(xiàn)象被稱為OverWrite,在這種情況下斑匪,其余物件的渲染(包括VS/FS)浪費(fèi)的呐籽。

上面陳述的是最簡單的前向渲染的基本思路與實(shí)現(xiàn)效果,實(shí)際上蚀瘸,還是可以通過一些方法來對前向渲染進(jìn)行優(yōu)化的:比如建立一個光源列表狡蝶,維護(hù)這個光源所覆蓋的物體的清單,在渲染的時候贮勃,按照光源來進(jìn)行渲染贪惹,可以避免shader分支的額外消耗,以及無關(guān)物件的計(jì)算消耗寂嘉,但是這種方式也需要通過多個pass來完成奏瞬,每個pass處理一個或者一組光源,之后將這些pass的輸出結(jié)果融合得到最終的輸出結(jié)果泉孩。

前向渲染的流程如圖所示

按照前向渲染的概念硼端,如果場景中有M個物體,N個光源寓搬,那么最壞的情況下显蝌,每個物體都處在所有光源的籠罩之下,那么最終需要處理的復(fù)雜度就是O(M * N)。每個光源對于物件上的像素的最終輸出是起著怎樣的一個作用呢曼尊,是各自獨(dú)立對物件施加影響,并在最后將這個顏色值相加嗎脏嚷?按照正常情況骆撇,一張白紙,在上面投下強(qiáng)度相同的紅光與綠光父叙,其最終顯示的顏色應(yīng)該是兩者的疊加神郊,從這個角度揣測,多種光源的作用下趾唱,獨(dú)立計(jì)算并疊加就可以了涌乳。在場景復(fù)雜度較高,或者光源數(shù)目較多的情況下甜癞,其渲染一幀所需要的時間代價是極為高昂的夕晓。如果能找到一種渲染方法,使得其進(jìn)行光照渲染的時間成本不隨場景復(fù)雜度而變化就好了悠咱,基于這種想法蒸辆,人們提出了延遲渲染(Deferred Rendering)框架。

對于場景中的每個物體析既,在渲染的時候都需要經(jīng)過Vertex Shader(VS)與Fragment Shader(FS)兩個處理階段:物體網(wǎng)格數(shù)據(jù)被分割成一個個的三角面片躬贡,三角面片中的頂點(diǎn)經(jīng)過VS的處理后,經(jīng)過光柵化(Rasterization)處理后變成一個個的Fragment眼坏,之后經(jīng)過FS的光照計(jì)算處理(實(shí)際上拂玻,光照處理也可以放在VS階段,不過其輸出結(jié)果往往呈現(xiàn)出不連貫的面片狀宰译,與真實(shí)世界的表現(xiàn)相差太遠(yuǎn)檐蚜,所以一般都將光照放在更為精細(xì)化的FS中處理,雖然消耗有所增長囤屹,但是效果是符合預(yù)期的)熬甚,光照處理完成后輸出到FrameBuffer中。

在前向渲染模式下肋坚,OverWrite會導(dǎo)致復(fù)雜場景存在極大的浪費(fèi)乡括。而延遲渲染可以將場景中的多個光源的計(jì)算處理過程一次性完成,且只有那些處在光源的覆蓋范圍內(nèi)的智厌,且最終在屏幕上可見的像素才會參與到光照計(jì)算中來诲泌,大大節(jié)省了時間成本?那么延遲渲染到底是怎么做到的呢铣鹏?

簡單來說敷扫,就是將光照的計(jì)算處理從之前的逐物體進(jìn)行,改為只在最終的的back buffer上進(jìn)行。這其實(shí)可以理解成是一種后處理(Post-process)葵第,準(zhǔn)確來說绘迁,是一個multipass post-process,其總體流程如\ref{deferred}所示卒密,總的來說缀台,可以分成三個pass:

  • 第一個pass用來對整個場景進(jìn)行渲染————world pass
  • 第二個pass用來對第一個pass輸出的結(jié)果進(jìn)行光照處理————lighting pass
  • 第三個pass負(fù)責(zé)將第二個pass的輸出結(jié)果顯示到屏幕上————present pass

G-Buffers

延遲渲染中,最關(guān)鍵核心的一個概念哮奇,就是Geometry Buffer膛腐,俗成G-Buffer。G-Buffer包含了屏幕上各個像素用于計(jì)算光照shading所需的全部元素(如坐標(biāo)數(shù)據(jù)鼎俘,法線數(shù)據(jù)哲身,深度數(shù)據(jù),材質(zhì)貼圖數(shù)據(jù)等贸伐,而通常情況下勘天,為了節(jié)省,一般坐標(biāo)數(shù)據(jù)是不需要存儲的棍丐,而是在需要的時候根據(jù)深度數(shù)據(jù)計(jì)算得到)误辑。G-Buffer 中常見的幾個元素有用于計(jì)算diffuse color 的基色貼圖Albedo,用于計(jì)算高光數(shù)據(jù)的Specular 貼圖(通常包含金屬度與粗糙度數(shù)據(jù)歌逢?)巾钉,還有光影計(jì)算必須的一些基礎(chǔ)元素如法線貼圖與深度貼圖等,其表現(xiàn)如圖所示:

一般來說秘案,如果將G-Buffer的數(shù)據(jù)都存儲在一張貼圖中砰苍,那么這個貼圖的單個像素的長度肯定非常大,而實(shí)際上阱高,G-Buffer的數(shù)據(jù)通常會分別存儲在多張貼圖中赚导,這就是我們俗稱的Multiple Render Target (簡稱MRT),而為了盡可能的節(jié)省帶寬與內(nèi)存赤惊,在如何對數(shù)據(jù)進(jìn)行存放也成為了一種藝術(shù)吼旧。如圖所示,此處一共使用了五張貼圖用于存儲G-Buffer 的數(shù)據(jù):

延遲渲染具體流程

延遲渲染未舟,一般可以分成兩個階段:第一個階段是geometry render階段圈暗,這個階段的輸入是頂點(diǎn)數(shù)據(jù),輸出則是G-Buffer的各種元素裕膀,在這個階段中员串,會處理之前前向渲染所應(yīng)該處理的除了光照之外的一切計(jì)算,將后續(xù)計(jì)算需要的結(jié)果存入G-Buffer中昼扛;第二個階段則是shading render階段寸齐,這個階段的輸入就是我們前一個階段的輸出,也就是G-Buffer數(shù)據(jù)。如前面所述渺鹦,這是一個后處理過程扰法,也就是說,從本質(zhì)上來說海铆,這就是一個復(fù)雜的Fragment/Pixel Shader執(zhí)行過程迹恐,這個階段會從G-Buffer中取出與當(dāng)前計(jì)算的Fragment相對應(yīng)的數(shù)據(jù),并對每個光照按照選定的光照方程(Light Equation)計(jì)算其光照輸出卧斟,之后各個光源的輸出按照一定的方式(Additive Blending)融合輸出到FrameBuffer中。

在多個光源的情況下憎茂,延遲渲染的流程大概可以用偽代碼來描述:

延遲渲染最終輸出到屏幕上的圖像表現(xiàn)跟前向渲染輸出的結(jié)果是一樣的珍语,不同的是調(diào)整了渲染管線中各個子環(huán)節(jié)的渲染順序,避免了許多不必要的計(jì)算與處理:

  • 如避免了我們前面提到的各種被遮擋元素的光照處理過程竖幔,只有最終會被顯示到屏幕中的像素才會經(jīng)過光照處理階段板乙,而要想在前向渲染中實(shí)現(xiàn)這個效果,就需要做實(shí)時的遮擋剔除拳氢,但是遮擋剔除的消耗比較高募逞,一般都是用在離線計(jì)算過程中的
  • 如避免了多個細(xì)小三角面片在單個像素上的多次計(jì)算消耗,如圖

從而實(shí)現(xiàn)了整個渲染過程的加速馋评。

延遲渲染算法的改進(jìn)

延遲渲染的優(yōu)點(diǎn)是:

  • 每個幾何體(geometry)只需要處理一次
  • 由于是對light進(jìn)行循環(huán)計(jì)算的放接,所以,每一個light的處理過程都是確定的留特,避免了前向渲染shader中雜七雜八的分支
  • 每次只處理一個light纠脾,不存在光源數(shù)目過多而導(dǎo)致寄存器不夠用的情況
  • 由于延遲渲染本來就是后處理的一種,因此對于各種后處理有比較好的兼容性(比如SSAO)

而其缺點(diǎn)則在于:

  • 由于G-Buffer的格式是固定的蜕青,所以其能夠提供的參數(shù)種類就是有限的苟蹈,導(dǎo)致其只能處理有限種類的光照情況,即所謂的Shading Model數(shù)目是有限的右核。
  • 由于G-Buffer中對于屏幕中的每個sample都只能存儲一條數(shù)據(jù)慧脱,所以延遲渲染無法處理需要前后多個sample參與的透明或者半透明的物體的渲染
  • 由于每次對光源進(jìn)行渲染的時候,都需要將G-Buffer數(shù)據(jù)加載一次贺喝,因而延遲渲染對于帶寬有較高的要求菱鸥。
  • 在上面的算法中,我們看到搜变,延遲渲染需要計(jì)算各個光源對于某個Fragment的contribution的采缚,這就意味著,對于任意一個Fragment挠他,任意一個光源扳抽,都要進(jìn)行一次評估,這就會導(dǎo)致shader處理的多分支情況的浪費(fèi)。而實(shí)際上贸呢,只有極少數(shù)的光源會對所有的Fragment 產(chǎn)生影響镰烧,而大多數(shù)的光源都只能覆蓋極少一部分Fragment。
  • 不支持MSAA
  • 在部分情況下楞陷,可能渲染效率要低于前向渲染(比如光照數(shù)比較少怔鳖,且場景簡單,overlap比較少的情況下)

對于上述的缺點(diǎn)固蛾,是否有較好的解決方案呢结执?實(shí)際上,是可以做一些改進(jìn)的艾凯,如:

  • 在一次pass中献幔,處理多個光源(這多個光源最好是在像素的覆蓋上有比較高的重合度,或者有其他相似之處從而可以通過合并部分計(jì)算來達(dá)到節(jié)省的作用趾诗,比如將平行光作為主光源進(jìn)行一次處理蜡感,對點(diǎn)光源組又進(jìn)行一次處理),從而避免G-Buffer 重載的次數(shù)恃泪,降低對FrameBuffer 的寫頻率

  • 在每個光源pass中郑兴,不再對所有的Fragment進(jìn)行處理,而是只處理那些光源可能覆蓋到的Fragment贝乎。

    • 將光源的覆蓋范圍看成一個geometry(這個geometry叫做light volume情连,形狀可以是box,也可以是sphere糕非,也可以是cone或者pyramid)蒙具,之后對這個light volume 進(jìn)行渲染與光柵化,過程與結(jié)果如圖所示:
過程
結(jié)果
  • 將light volume光柵化后覆蓋到屏幕上的形狀朽肥,并計(jì)算出一個能覆蓋住這個形狀禁筏,且與屏幕的坐標(biāo)軸對齊的quad,這種方法被稱作Quad-based Culling衡招。實(shí)際上最開始提出精確控制光源覆蓋范圍這個思路的時候篱昔,考慮的是使用一個能精確代表光源形狀的幾何體來計(jì)算其覆蓋范圍,但是這種方式會導(dǎo)致需要處理大量的面片和頂點(diǎn)數(shù)據(jù)始腾,成本略高州刽,后來考慮直接用一個或者幾個BoundingBox 來模擬其形狀,方法簡單且計(jì)算高效浪箭。而在計(jì)算光源能影響的像素?cái)?shù)據(jù)的時候穗椅,有兩種方式,一種是對每個光源使用stencil 來判定其是否被覆蓋奶栖,這種方式需要進(jìn)行兩個pass處理匹表,過程繁瑣且低效门坷;另一種方式則是直接使用depth test 來判定當(dāng)前的光源是否能夠覆蓋到當(dāng)前像素(將當(dāng)前像素變換到光源空間中,與shadow map比較袍镀?)默蚌。

  • 降低每個光源需要從G-Buffer中讀取的數(shù)據(jù)尺寸或者讀取頻率,或者降低寫入頻率苇羡,這可以通過Deferred Lighting或者Light Pre-Pass的方式來實(shí)現(xiàn)绸吸,其步驟大致如下:

    - 將diffuse與specular拆解成兩個獨(dú)立的元素,分別進(jìn)行計(jì)算设江。在這種情況下锦茁,可以只用單色來表示Specular,雖然這種做法是物理不正確的叉存,但是其效果表現(xiàn)差異非常小蜻势,基本可以忽略,從而可以節(jié)省兩個float數(shù)據(jù)的讀入鹉胖。
    - 將與光源無關(guān)的元素(如Surface Albedo)單獨(dú)拎出來,提前加載到顯存中够傍,避免對于每個光源都進(jìn)行一遍加載甫菠。
    - 對于每個光源而言,將它們計(jì)算結(jié)果的diffuse與specular等元素分別進(jìn)行相加
    - 最后冕屯,通過一個Resolve Pass寂诱,將diffuse與specular等元素合并起來。而這個過程可以通過SIMD得到加速安聘。(有人可能會覺得將diffuse與specular拆解出來計(jì)算痰洒,在最后合并的時候可以選擇多種靈活的方式來得到更好的效果,但實(shí)際上光照方程中精彩的變化點(diǎn)都出現(xiàn)在diffuse與specular的內(nèi)部計(jì)算中浴韭,在外部合并處反而沒有太多嚼頭丘喻,所以從這個方面來說,拆開diffuse與specular并沒有太大收益)
    

Tile-based Deferred Shading是另外一種對延遲渲染進(jìn)行提速的實(shí)現(xiàn)算法念颈。其基本思想是將G-Buffer分割成一個個的tile泉粉,之后對于每個tile,計(jì)算各個光源是否與之相交(注意榴芳,在Z軸上是需要比較MinZ與MaxZ的)嗡靡,之后對覆蓋到這個tile的光源進(jìn)行處理,即每個tile 加上若干光源作為一個group窟感,之后逐group 的進(jìn)行處理讨彼。而這種思想通過借助于GPU的SIMD特性實(shí)現(xiàn)CPU并行計(jì)算功能的compute shader,可以得到極大的加速:

  • 由于是逐tile處理的柿祈,所以G-Buffer的數(shù)據(jù)就不需要全盤加載讀入了哈误,而且對于FrameBuffer也不再是全盤寫入了哩至。
  • 對于光源數(shù)據(jù),也不需要將所有的光源數(shù)據(jù)都讀入并處理黑滴,而是只處理與當(dāng)前處理的tile相關(guān)的數(shù)據(jù)即可憨募。
  • 降低了光源處理的復(fù)雜度,不再需要對所有的像素進(jìn)行光源可見性判定袁辈,只需要經(jīng)過一次粗糙的tile可見性判定撤师,加上tile內(nèi)的精細(xì)判定就可以保證無遺漏了私蕾。
  • 這個方法是以tile中的像素為核心進(jìn)行的,每個像素都需要對所有tile相關(guān)的光源進(jìn)行一次計(jì)算,所以對于光源而言翅阵,不需要在shader中進(jìn)行分支計(jì)算。

這種方法的具體思路大概如圖所示:

其實(shí)施效果大致如圖所示觉既,可以看到昂羡,場景中光源數(shù)目越多,這種算法對于幀率提升的幅度也越高鸣皂。

而Quad-based Culling與Tile-based Culling的效果對比如圖所示抓谴,可以看到在光源數(shù)目越多的情況下,Tile-based Culling方法的收益越高:

關(guān)于Tile-based Culling與Deferred Shading以及Deferred Lighting(因?yàn)槭褂昧藛紊玸pecular而導(dǎo)致性能有所提升)寞缝,也有相關(guān)的對比數(shù)據(jù)癌压,如圖:

延遲渲染與MSAA

我們知道,MSAA是對于場景中的每個三角面片荆陆,都對其覆蓋的每個像素進(jìn)行一次FS/PS計(jì)算滩届,之后將結(jié)果賦予這個像素中被三角面片所覆蓋的采樣點(diǎn)sample,最終在輸出最終圖像的時候被啼,就將單個像素中所有sample的值加起來求平均帜消。

而從剛才描述的延遲渲染的實(shí)現(xiàn)流程來看,在最終計(jì)算輸出到屏幕的FrameBuffer的結(jié)果時浓体,已經(jīng)沒有所謂的三角面片泡挺,每個G-Buffer 的像素只有一個sample數(shù)值,不再存在多個顏色sample汹碱,以便在最終輸出的時候進(jìn)行相加求平均了(而這也是透明或者半透明物件的渲染與延遲渲染不兼容的原因)粘衬,所以,從這個角度來看咳促,延遲渲染與MSAA 算法是不兼容的稚新。

不過從MSAA的原理上來看,我們實(shí)際上可以用類似SSAA的方式來實(shí)現(xiàn)類似的MSAA跪腹,即只對面片的邊緣處進(jìn)行per-sample的計(jì)算(每個像素多次計(jì)算)褂删,而對于其他完全被面片覆蓋的像素處,則只進(jìn)行per-pixel的計(jì)算即可冲茸。當(dāng)然屯阀,數(shù)據(jù)的存儲量變成了多倍(比如最常見的2x2就是4倍)缅帘,不過這些數(shù)據(jù)在其他場景中也是有用的,比如可以用在shadow map上消除鋸齒难衰。

而要實(shí)現(xiàn)上述MSAA钦无,首先需要解決的問題,就是需要偵測到圖像的邊緣盖袭,通常對邊緣的檢測有以下幾種方式:

  • 通過深度對比失暂,找出深度不連續(xù)的(比如使用深度的導(dǎo)數(shù),也就是相鄰sample的深度的差的趨勢來判定是否發(fā)生了轉(zhuǎn)折)鳄虱,即為邊緣
  • 對于曲面來說弟塞,深度檢測方法可能會失效,因此對于這種情況拙已,可以考慮使用sample上的shading normal(這跟普通的normal有什么區(qū)別决记?)來進(jìn)行檢測,如果相鄰sample的normal差距過大倍踪,可能就是曲面的邊緣了
  • 上面兩種檢測方法已經(jīng)足以應(yīng)付絕大多數(shù)情況了系宫,不過由于邊緣檢測的實(shí)現(xiàn)是開發(fā)者自己完成,所以也可以采用一些自認(rèn)為合適的方法來進(jìn)行建车。

這種自己實(shí)現(xiàn)的MSAA方法跟前向渲染中的MSAA方法對比笙瑟,還有自己獨(dú)特的好處,比如對于邊緣比較光滑的三角面片的交界處癞志,并不需要進(jìn)行逐sample的渲染,進(jìn)一步降低了計(jì)算量框产。

在Quad-based Deferred Rendering中使用MSAA一般首先要先辨別邊緣像素凄杯,之后才對邊緣像素進(jìn)行per sample采樣計(jì)算。而辨別邊緣的方式又可以分成shader branch以及stencil兩種秉宿,shader branch效率低戒突,而stencil則需要使用兩個pass(一個標(biāo)記per sample像素并渲染,另一個標(biāo)記per pixel像素并渲染)描睦,這就會導(dǎo)致需要對光照進(jìn)行兩次Culling操作膊存,雖然如此,但還是比shader branch速度快忱叭。

在Tile-based Deferred Rendering中使用MSAA相對于Quad-based Deferred Rendering中有所改進(jìn)隔崎,per sampler以及per pixel的渲染都是放在一個shader pass中完成,且為了避免shader branch韵丑,在shader的主流程中只處理sample 0的計(jì)算結(jié)果爵卒,而像素中剩下的sample則通過computer shader的多線程計(jì)算功能分散到其他線程中完成。

兩種方式實(shí)施的性能對比如圖所示:

Deferred Shading 與 Deferred Lighting

在延遲渲染的概念中撵彻,經(jīng)常會出現(xiàn)Deferred Shading以及Deferred Lighting的說法钓株,這兩者分別代表什么意思实牡,又有什么區(qū)別呢?

實(shí)際上轴合,Deferred Shading就是我們前面所描述的Deferred Rendering的內(nèi)容:對所有的物體進(jìn)行一遍渲染创坞,將后續(xù)LIghting/Shading 所需要的所有數(shù)據(jù)存入G-Buffer,之后通過多個pass對多個燈光進(jìn)行Lighting+Shading后進(jìn)行混合受葛,或者只用一個pass對所有的光源進(jìn)行處理并輸出結(jié)果题涨,流程如圖所示。

deferred shading

與Deferred Shading不同奔坟,Deferred Lighting將Lighting與Shading分開携栋,在Lighting階段,只處理光照相關(guān)數(shù)據(jù)咳秉,并將結(jié)果輸出到一個Normal Buffer中(如這個Buffer中可能只包含Normal婉支,Depth以及Specular相關(guān)參數(shù),Normal占用兩個float澜建,剩余兩個參數(shù)各占一個向挖,如果Lighting階段只需要輸出一個Normal Buffer就足夠的話,那么就可以去除Deferred Rendering對于MRT的限制炕舵,同時也可以避免MRT 帶來的帶寬與OverWrite浪費(fèi))何之,Lighting 的輸出結(jié)果是Diffuse+Specular Color,在有些項(xiàng)目中咽筋,為了將這兩者輸出到一張Buffer 中溶推,而選擇將Specular 壓縮到一個通道中(單色Specular 在絕大部分情況下其實(shí)基本上都是夠用的)。Lighting 之后奸攻,就進(jìn)入了Shading 階段蒜危,在這個過程中,將Lighting階段得到的光照數(shù)據(jù)取出來睹耐,對物體進(jìn)行Shading辐赞,為了能夠處理物體材質(zhì)相關(guān)的邏輯(比如支持頭發(fā),次表面散射硝训,自發(fā)光等)响委,在這個階段會對所有的物體再進(jìn)行一次Geometry Pass (由于之前已經(jīng)獲得了全場景的Depth 數(shù)據(jù),這一次的Geometry Pass 要快上很多)窖梁,各個物體的材質(zhì)相關(guān)數(shù)據(jù)如Albedo 貼圖信息等都可以在進(jìn)行Geometry Pass的過程中直接取到赘风,從而可以根據(jù)不同的材質(zhì)實(shí)現(xiàn)不同的渲染方式。 其流程如圖所示纵刘。

deferred lighting

通常來說贝次,相對于Deferred Lighting而言,Deferred Shading的主要的局限性在于:

  • 后續(xù)lighting與shading所需數(shù)據(jù)較多彰导,導(dǎo)致需要使用多個Render Target才能完成必須數(shù)據(jù)的輸出蛔翅,導(dǎo)致較高的帶寬占用
  • 在進(jìn)行Geometry渲染階段時敲茄,Depth Buffer是逐漸生成的,在生成的過程中山析,其實(shí)會導(dǎo)致較多的overwrite(GBuffer生成時的Overwrite)堰燎,而由于G-Buffer 的數(shù)據(jù)比較復(fù)雜,導(dǎo)致這部分浪費(fèi)的計(jì)算量也比較大
  • 在這種模式下笋轨,如果需要對不同的mesh指定不同的材質(zhì)秆剪,以實(shí)現(xiàn)不同的渲染效果(如自發(fā)光,次表面散射爵政,頭發(fā)等)就需要在G-Buffer 中增加額外的空間用以輸出相應(yīng)的信息仅讽,而這些特定的材質(zhì)往往只占據(jù)著極少部分像素,導(dǎo)致存儲這些信息的大部分的像素其實(shí)都是浪費(fèi)的钾挟。

在Deferred Lighting模式下洁灵,Geometry Rendering階段的所有輸出,只需要用以支持Lighting即可掺出,從而大大減少了前面提到的Deferred Shading的OverWrite導(dǎo)致的浪費(fèi)徽千,且因?yàn)長ighting需要的信息比較少,比如只需要Normal數(shù)據(jù)+Depth數(shù)據(jù)+Specular數(shù)據(jù)(在不那么挑剔的情況下汤锨,這些數(shù)據(jù)可以直接塞入一張buffer中双抽,從而擺脫平臺不支持MRT的限制),從而也可以避免Deferred Shading的高帶寬消耗闲礼。但是牍汹,需要注意的是,Deferred Lighting也有著自身的缺陷:

  • 最顯著的缺陷在于柬泽,Geometry會被渲染兩次柑贞,雖然后面一次由于Early-Z的原因,消耗得到很大程度的降低聂抢,整個過程的消耗依然不容小覷。
  • 由于在Shading階段會需要完成Geometry處理與Shading兩部分內(nèi)容棠众,所有Pixel Shader不可避免的會被分割成Geometry部分與Shading部分琳疏,從而導(dǎo)致Pixel Shader的指令的實(shí)施效率的降低。

實(shí)際上闸拿,仔細(xì)分析空盼,相對于Deferred Shading,Deferred Lighting只是將Lighting與Shading分開(一個Pixel Shader變成兩個新荤,處理的功能不變)揽趾,另外增加了一次Geometry Pass(相當(dāng)于增加了一個Vertex Shader處理),從前面的優(yōu)劣對比猜想這兩者的性能消耗不一定會有比較大的差距苛骨,但實(shí)際上篱瞎,大部分情況下Deferred Lighting對于Deferred Shading的改進(jìn)都無法抵消新增的Vertex Shader的消耗苟呐,導(dǎo)致在絕大部分情況下,Deferred Shading的性能都要更勝一籌俐筋。

針對Deferred Lighting的優(yōu)勢與弊端牵素,有人整出了一種混合Deferred Rendering的方式[Hybrid Deferred Rendering,Marries van de Hoef]澄者,其基本Pipeline如圖所示:

其渲染效率對比如圖所示:

延遲渲染下的陰影實(shí)現(xiàn)方式

在延遲渲染模式下笆呆,主要有以下幾種實(shí)現(xiàn)陰影的方式:

  • Stencil Shadow。在進(jìn)行光照處理的同時粱挡,對那些光照覆蓋的位置進(jìn)行stencil處理赠幕,最后使用stencil的數(shù)值來判定當(dāng)前是否處于陰影區(qū)域內(nèi)。不過這種方式只能用來實(shí)現(xiàn)硬陰影询筏,對于軟陰影就無能為力了榕堰。
  • Shadow Map。對于每個光源屈留,生成一張類似于深度貼圖的Shadow Map(從光源的角度出發(fā))局冰,之后在進(jìn)行l(wèi)ighting的時候,將像素轉(zhuǎn)換到光源空間與shadow map進(jìn)行比對而判斷是否處于陰影中灌危。這種方式康二,對于每個光源都需要產(chǎn)生一張shadow map,消耗比較高勇蝙,所以沫勿,一般只對主光源(平行光)使用,其他光源采用其他方式味混〔ⅲ或者在手機(jī)等平臺上,直接使用離線渲染的方式將多個光源的shadow map合成稱為一個light map翁锡,用于運(yùn)行時渲染蔓挖。
  • 平面陰影。將物件投射到某個平面上馆衔,產(chǎn)生一個物件的平面形狀瘟判。這種方式限制比較多,比如對于處于曲面上的物體角溃,其陰影可能會穿幫拷获,又對于一些可以在Y軸上下沉一段距離的物體,其表現(xiàn)也不盡人意减细。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末匆瓜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驮吱,老刑警劉巖茧妒,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糠馆,居然都是意外死亡嘶伟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進(jìn)店門又碌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來九昧,“玉大人,你說我怎么就攤上這事毕匀≈ィ” “怎么了?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵皂岔,是天一觀的道長蹋笼。 經(jīng)常有香客問我,道長躁垛,這世上最難降的妖魔是什么剖毯? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮教馆,結(jié)果婚禮上逊谋,老公的妹妹穿的比我還像新娘。我一直安慰自己土铺,他們只是感情好胶滋,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悲敷,像睡著了一般究恤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上后德,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天部宿,我揣著相機(jī)與錄音,去河邊找鬼瓢湃。 笑死理张,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箱季。 我是一名探鬼主播,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼棍掐,長吁一口氣:“原來是場噩夢啊……” “哼藏雏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤掘殴,失蹤者是張志新(化名)和其女友劉穎赚瘦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奏寨,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡起意,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了病瞳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揽咕。...
    茶點(diǎn)故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖套菜,靈堂內(nèi)的尸體忽然破棺而出亲善,到底是詐尸還是另有隱情,我是刑警寧澤逗柴,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布蛹头,位于F島的核電站,受9級特大地震影響戏溺,放射性物質(zhì)發(fā)生泄漏渣蜗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一旷祸、第九天 我趴在偏房一處隱蔽的房頂上張望耕拷。 院中可真熱鬧,春花似錦肋僧、人聲如沸斑胜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽止潘。三九已至,卻和暖如春辫诅,著一層夾襖步出監(jiān)牢的瞬間凭戴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工炕矮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留么夫,地道東北人。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓肤视,卻偏偏與公主長得像档痪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子邢滑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評論 2 348