文章出處
在上面我描述中,我們發現,不管哪一種管線。都會涉及到幾個部分。 1、光照計算 2、透明渲染 3、陰影計算 4、圖像輸出。 那Unity3D又是如何對這些進行統一流程控制的呢。我們看下面的圖就明白了。
Unity3D渲染管線圖
總的來說,Unity3D的渲染管線還算穩定和易用,其的渲染管線包含了常見的三種方案。最主要目的還是在想著光照計算和效果顯示的處理。同時保持對上層透明。其Graphics Commander Buffer提供了擴展管線的能力。而Graphics設置面板里,也提供了自定義延遲管線Shader的功能。然而也有諸多的美中不足,比如,正交攝像機模式下,不能使用延遲渲染技術。 延遲光照下無法實現PBR和實時環境反射抽取等等。
文章列表


關于《Thinking in Unity3D》
筆者在研究和使用Unity3D的過程中,獲得了一些Unity3D方面的信息,同時也感嘆Unity3D設計之精妙。不得不說,筆者最近幾年的引擎研發工作中,早已習慣性的從Unity3D中尋找解決方案。
Unity3D雖比不上UE那么老練沉穩,氣勢磅礴。也比不上CE那樣炫麗多姿,盛氣凌人。但它的發展勢如破竹,早已遍地生花!故而在此記錄一些自己的心得體會,供大家參詳交流。若有欠妥之處,還望各位及時指正。
HI,你好
Unity3D發展至今,已經是5.x版本了。對于一個引擎迭代來說,特性、效果、效率的提升,無不波及到渲染管線的改動。而與渲染管線最為緊密掛鉤的就是材質系統和渲染流程,但由于材質系統和渲染流程涉及的范圍和內容更廣。我們將用單獨的篇幅來描述。本文主要目標是渲染管線中的Rendering Path。
由于歷史發展,以及各種平臺、機型、版本兼容的原因。Unity3D中,目前保存了4種Rending Path.
1、Deferred Shading Rendering Path(延遲渲染)
2、Forward Rendering Path(前向渲染)
3、Lagacy Deferred Lighting Rendering Path(延遲光照)
4、Vertex Lit Rendering Path(頂點光照)
Forward Rendering Path(前向渲染)
傳統的前向著色渲染方式是一種簡單粗暴的方式。就是一次性將一個物體繪制完再繪制下一個。光照計算也是如此。前向著色最主要的問題就是光照問題。當光源過多的時候,就需要進行處理。 而Unity3D在光源處理方面,也結合了像素光照(per-pixel lighting) ,頂點光照(per-vertex lighting),球諧光照(Spherical Harmonics lighting)等多種方案,其復雜程度可見一斑。
Unity3D中前向渲染的光源策略
前向著色渲染由于效率和寄存器限制等原因。不可能老老實實地去處理所有的光源。因此,需要根據光源的遠近,范圍,重要程度等因子決定計算方式。
1、如果一個光源的RenderMode沒有設置為重要(Important),那么它將永遠是逐頂點或者球諧光照計算方式。
2、最亮的(Brightest)方向光源會做為逐像素光照計算。
3、如果一個光源的RenderMode設置為重要(Important),那么它將會采用逐像素光照計算方式
4、如果上面的結果中的用于逐像素計算的光源數目小于了Project Settings->Quality面板中的Pixel Light Count值。 為了減少亮度誤差,有一些光源會被當作像素光源計算(PS:非像素光源無法完全計算陰影關系。會導致場景偏亮)。
5、Unity3D對頂點光照,像素光照做了最大限制。 分別為4個。而場景中不可能只有這么多光源。因此,使用了一個優先級判定。
.png)

左:光源位置圖 右:光源分配圖
從圖中我們可以看到。 D參與了像素和頂點光照。 G參與了頂點光照和球諧光照。 這樣的處理應該是為了做一個光照信息的平滑銜接,不至于變得很突兀。
Unity3D中前向渲染的光照的計算過程
前向渲染中,光照計算被分成了多個PASS。通常它們由1*FarwardBase Pass + N*FarwardAdd Pass組成。可以看出,光源的數目在前向渲染管線中是一個致命的效率殺手。
1、Base Pass 提交一個逐像素方向光和所有的逐頂點光照和球諧光照。
2、Additional Pass 提交一個逐像素的光照計算。 如果一個物體受更多的光源影響。那么就會有許多PASS需要進行繪制。
注:在Shader中。可以指定FarwardBase來關掉Additional 功能。
注:在前向渲染中,只能有一個方向光實時陰影。
Unity3D中的球諧光照
球諧光照是一個CPU光照算法。它可以處理大規模的光源信息,非常適合一些很小的動態點光源。但是它存在以下幾個問題。
1、球諧光照是基于物體頂點的算法,并非像素級。這就意味著它不能使用一些像素級的效果增強手段。比如法線貼圖。
2、基于效率的考慮,球諧光照的更新頻率非常低。如果光源移動過快,就會穿邦。
3、球諧光照是基于全局空間的計算,當一個面離點光源或者聚光燈很近時,效果是錯的。
Deferred Shading Rendering Path(延遲渲染)
延遲渲染技術簡介
延遲渲染技術已經是一個成熟且穩定的技術。已經廣泛用于各種商業引擎中。它主要解決的是當光源數目過多時帶來的復雜光照計算的開銷。 在傳統前向渲染中,假設一個場景中有M個物體,N個光源。 那么理論上進行的光照計算次數為 M*N。 而DS管線可以使其變為M+N。
但是DS管線并非萬能的。有以下情況需要注意
延遲渲染技術缺陷
1、DS需要多渲染目標(MRT)的支持、深度紋理、雙面模板緩存。
這個特性,需要顯卡支持SM3.0的API。2006年以后的PC顯卡應該不成問題。比如GeForce 8xxxx,AMD Radeon X2400,Intel G45以后的顯卡。
2、DS管線會消耗更多的顯存,用于緩存G-Buffer。同時,會要求顯卡擁有更大的位寬(bit counts)。
在手機上目前(2016年)還不實現。
3、DS管線無法處理半透明物體。
半透明物體需要退回到傳統前向渲染中進行
4、硬件抗鋸齒(MSAA)無法使用。
只能使用一些后期算法,如FXAA等。
5、這句話中的內容目前未測試,故無法準確體會其中的意思:There is also no support for the Mesh Renderer’s Receive Shadows flag and culling masks are only supported in a limited way. You can only use up to four culling masks. That is, your culling layer mask must at least contain all layers minus four arbitrary layers, so 28 of the 32 layers must be set. Otherwise you will get graphical artefacts.
延遲渲染技術在Unity3D中的實現方案
Unity3D中,延遲渲染管線為分兩個階段進行。G-Buffer階段和光照計算(Lighting)階段。
G-Buffer階段
Unity3D渲染所有的非透明對象到各個RT中,RT的內容分布見 G-Buffer內容。Unity3D將各個RT做成了全局變量,方面Shader中進行操作。像這樣:CameraGBufferTexture0 .. CameraGBufferTexture3
光照計算階段
這個階段的主要目的就是根據G-Buffer的內容進行光照計算。由于是屏幕空間的計算,顯然要比之前的前向渲染來得容易得多。
注:實時陰影的計算是在光照計算之前的。 DS管線并不能減少實時陰影的開銷。應該怎么整還得怎么整。最后,每個物體受到的實時陰影的影響會疊加到RT3中。一些特殊的爆光效果,Lightmap光影貼圖效果等都會進入RT3。 參見G-Buffer內容
G-Buffer內容
•RT0, ARGB32 format: Diffuse color (RGB), occlusion (A).
•RT1, ARGB32 format: Specular color (RGB), roughness (A).
•RT2, ARGB2101010 format: World space normal (RGB), unused (A).
•RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps + reflection probes buffer.
•Depth+Stencil buffer.
•RT1, ARGB32 format: Specular color (RGB), roughness (A).
•RT2, ARGB2101010 format: World space normal (RGB), unused (A).
•RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps + reflection probes buffer.
•Depth+Stencil buffer.
注:為了減少顯存和渲染開銷。當前場景的攝像機開啟了HDR模式時,RT3將不會被創建。而是直接使用攝像機的HDR RT。
自定義DS管線
Unity3D中,標準的DS管線是Standard系列。如果你想修改某一個部分。你可以新建一個自己的Shader。然后替換掉默認的即可。
替換的位置在Edit->Project Settings->Graphics面板中。把Deferred屬性下拉框變成Custom,就可以進行替換操作了。
.png)

內置Shader設置
Lagacy Deferred Lighting Rendering Path(延遲光照)
注:從5.0開始,DL渲染已經不被Unity3D推薦,Unity3D更推薦大家新項目使用DS管線方式。因為DL方式不好實現基于PBR著色的Standard材質,以及場景反射。
注:如果攝像機設置為了正交投影。會強制退回前向渲染
注:DL也不會降低實時陰影的開銷
和DS渲染管線一樣,DL的出現同樣是為了解決光照計算的復雜度問題。然后不同的是,DL僅僅把光照計算拿出去了。簡單說來,DL管線工作流程如下。
步驟一、渲染場景中的對象,輸出光照計算需要的RT(深度、法線、高光信息)
步驟二、使用上面的RT進行光照計算
步驟三、再次渲染場景中的對象,并與計算機來的光照信息結合。
不難看出,DL相比DS而言,不需要大量的G-Buffer支持。甚至不需要MRT的支持。但是對深度圖的要求是必須的。如果遇上無法訪問深度BUFFER的情況。那就需要做一次Pre-Depth Pass渲染。
比起DS而言,DL由于不需要MRT的支持。在硬件特性需求和位寬上,少了許多開銷。
1、SM3.0
2、PC:GeForce FX、Radeon X1300、Intel 965 / GMA X3100
3、Mobile:所有支持OpenGL ES 3.0的設備,部分支持OpenGL ES 2.0的設備。
Vertex Lit Rendering Path(頂點光照)
注:這不是一個通用的技術名詞,只有Unity3D中有。
注:主機平臺這個不頂用。
注:不支持實時陰影和高精度高光計算。
Vertex Lit Rendering就是指,所有的光照計算都通過頂點進行。而在Unity3D中,它的主要目的是為了支持那些沒有可編程管線的設備。VL也提供了幾種方法,用于支持不同的材質類型。
1、Vertex 使用Blinn-Phong進行光照處理,針對沒有lightmap的對象使用。
2、VertexLMRGBM 針對lightmap貼圖使用RGBM加密(PC和主機平臺)的對象, 沒有額外的光照計算。
3、VertexLMM 針對lightmap貼圖使用double-LDR加密(移動平臺)的對象,沒有額外的光照計算。
Unity3D對幾種渲染管線的統一處理
在上面我描述中,我們發現,不管哪一種管線。都會涉及到幾個部分。 1、光照計算 2、透明渲染 3、陰影計算 4、圖像輸出。 那Unity3D又是如何對這些進行統一流程控制的呢。我們看下面的圖就明白了。

從圖中我們可以看到。Unity3D的傳統渲染管線和延遲渲染管線,在非透明物體渲染和光照階段是分離的。當處理完以后,緊接著處理非透明圖像效果->天空盒->透明物體渲染->后期效果。
結束語
總的來說,Unity3D的渲染管線還算穩定和易用,其的渲染管線包含了常見的三種方案。最主要目的還是在想著光照計算和效果顯示的處理。同時保持對上層透明。其Graphics Commander Buffer提供了擴展管線的能力。而Graphics設置面板里,也提供了自定義延遲管線Shader的功能。然而也有諸多的美中不足,比如,正交攝像機模式下,不能使用延遲渲染技術。 延遲光照下無法實現PBR和實時環境反射抽取等等。
參考文獻
文章列表
全站熱搜