着色器用於定義對象的外觀(材質屬性)以及它對光的反應,因爲必須在着色器中構建光照計算,然而可能會存在很多類型的光影,所以編寫Shader是非常麻煩的一件事。Unity爲了簡化編寫Shader的操作,提供了Surface Shaders,它會將所有的光照,陰影,光照貼圖,向前渲染和延遲渲染都會自動處理。
如何選擇渲染通道(Pass)以及燈光如何應用,都取決於採用什麼樣的渲染路徑。Shaer中的每個Pass適用於什麼樣的渲染路徑都是通過PassTags中的LightMode 來定義的。
Unity中包含的渲染路徑有:
渲染路徑 | 支持的LightMode |
---|---|
Forwawrd Rendering(正向渲染) | ForwardBase和ForwardAdd Pass會被使用 |
Deferred Shading(延遲着色) | Deferred Pass會被使用 |
legacy Deferred Lighting(遺留 延遲光照) | PrepassBase和PrepassFinal Pass會被使用 |
legacy Vertex Lit(遺留 頂點光照) | Vertex,VertexLMRGBM和VertexLM Pass 會被使用 |
上述任何一個渲染路徑,爲了渲染陰影或深度紋理,ShadowCaster Pass會被使用 |
Forward Rendering path(正向渲染路徑):
在Forward Rendering 路徑中,在影響對象的所有燈光中,一些最亮的燈會以逐像素的方式進行照明,然後會有4個燈光以逐頂點的方式進行照明,剩餘的燈光會以SH(球面諧波)的方式進行渲染。主要規則如下:
1.將渲染模式設置爲"Not Important"的燈始終是按頂點或者SH進行渲染
2.最亮的平行光會以逐像素的方式進行渲染。
3.將渲染模式設置爲“Important”的燈始終爲逐像素進行渲染。
4.最多會有4個光源按照逐頂點的方式進行渲染
5.經過以上操作後,如果逐像素渲染的燈光個數小於Quality Setting設置中Pixel Light Count的數量話,會按照亮度從高到低的順序,選擇合適的燈光數量,進行逐像素渲染。
渲染流程如下:
1.Forward Base Pass 會執行最亮的逐像素平行光和所有的逐頂點/SH燈光渲染。
2.Forward Add Pass 會在每個逐像素燈光(除逐像素平行光以外的)進行一次渲染。
例如:
上圖中,對象(圓圈)受到燈光A到H的影響,假設A到H都具有相同的顏色和強度,且所有燈光都具有自動渲染模式,所以他們將按照與對象距離來進行排序,前面的燈光會以逐像素的方式進行渲染(A-D,具體數量會根據質量設置中的數據來設置),然後就是以逐頂點的燈光渲染(D-G,最到4個燈光),剩餘的燈光會以SH(G-H)的方式進行渲染。如圖:
注意,在不同的模式渲染中有重疊渲染的部分,這樣當物體和光線移動時,不會出現太多的"燈光跳躍"
除A燈光外,其餘逐像素渲染燈光會調用Forward Add Pass。
ForwardBase :使用一個逐像素平行光和所有SH/頂點光源渲染對象,在此過程中還會添加着色器中的光照貼圖,環境光和自發光。在此渲染過程中方向光可以具有陰影(注意光照貼圖對象不會從SH燈獲取照明)。
如果在Pass中使用了“OnlyDirectional”標籤,ForwardBase 通道僅渲染主方向光,環境/光探測器和光照貼圖(SH和頂點光不包括在Pass數據中)。
ForwardAdd :會爲所有影響該對象的逐像素光源渲染一次(除主平行光外) 。默認情況下,這些過程中的燈光是沒有陰影的,除非使用了multi_compile_fwdadd_fullshadows這樣的編譯指令,來生成多個着色器程序變體。
如果着色器沒有提供適當的Pass(即沒有ForwardBase也不存在ForwardAdd),則該對象的渲染方式語Vertex Lit 路徑中的渲染方式相同。
SH(球面諧波)的渲染速度是非常塊的,並且在CPU上的成本很低,實際上可以自由地應用GPU(ForwardBase通道總是計算SH照明,由於SH的工作方式,所以無論多少SH燈,成本都是一樣的)。
SH的缺點有:
1.它們是在頂點的基礎上進行計算,所以不支持Cookie和法線貼圖
2.SH照明頻率很低,無法有明顯的照明過度。也隻影響漫反射光照(鏡面高管的頻率太低)。
3.SH照明不是局部的,靠近某些表面的球諧函數點光源或聚光燈會看起來有些彆扭。
Deferred shading Rendering path(延遲着色渲染路徑):
使用Deferred shading 時,對可影響GameObject的燈光數量沒有限制,所有燈光都會按逐像素的方式評估光照,所以它們可以與法線題圖等正確交換,所有的燈光都可以有Cookie和陰影。
Deferred shading 的優點:
照明的處理開銷與光照的像素數量成正比,這是由場景中光的大小決定,而不是它照亮了多少遊戲物體,因此可以通過保持較小的光線來提高性能。
延遲着色也具有高度一致和可預測的行爲,每個光的效果都是按像素計算的,因此沒有在大三角形上分解的光照計算。
Deferred shading 的缺點:
延遲照明沒有真正的抗鋸齒支持,也無法處理半透明的GameObject(這些是使用Forward Rendering渲染的)。
Mesh Render(網格渲染器)和Receive Shadows(接收陰影)標誌也不支持。
剔除遮蔽圖的支持方式有限(最多可以使用四個剔除遮蔽圖,即:剔除層遮蔽圖必須至少包含減去 4 個任意層後的所有層,所以 32 層中必須設置 28 層。否則會得到圖形假象。)。
使用要求:
1.需要具有多個渲染目標(MRT)的顯卡,Shader Model 3.0(或以上)的圖形卡,並支持深度渲染紋理。2006年後大多數pc顯卡都支持延遲着色,從GeForce 8xxx,Radeon x2400,Intel G45開始。
2.移動設備上不支持,主要由於使用MRT格式(某些GPU支持多個渲染目標,但只支持非常有限的位數)。
3.使用正交投影時,不支持延遲渲染。如果相機的投影模式設置爲'Orthographic(正交)',則相機會退回到“Forward Rdndering”。
性能:
延遲着色中的實時光的渲染開銷與光照像素的數量成正比,與場景複雜度無關,所以小的點光等和聚光燈在性能上更有優勢。如果它們被場景遊戲對象完全或部分遮擋,可能會獲得更好的效果。
有陰影的燈光比沒有的陰影的燈要耗費的性能更多,在延遲渲染中,陰影投射的遊戲對象仍然需要爲每個陰影投射光渲染一次或多次。此外,應用陰影的光照着色器比禁用陰影時使用的渲染開銷更高。
細節:
使用延遲渲染着色時,Unity中的渲染過程分爲兩步:
G-buffer Pass:遊戲對象被渲染成具有漫反射色、高光色、平滑度、世界空間法線、發射和深度的屏幕空間緩衝器。
Lighting Pass:先前生成的緩衝區用於將照明添加到發射緩衝區。
不能處理延遲渲染的着色(物體),在該過程完成後會使用Forward Rendering 路徑進行渲染。
默認g-buff佈局:
RT0,ARGB32格式:漫反射顏色(RGB),遮擋(A)。
RT1,ARGB32格式:鏡面反射顏色(RGB),粗糙度(A)。
RT2,ARGB2101010格式:世界空間標準(RGB),未使用(A)。
RT3,ARGB2101010(非HDR)或ARGBHalf(HDR)格式:Emission+lighting+lightmaps+reflectin 偵探 緩衝。
深度+模板緩衝區。
默認的g緩衝區佈局時160位/像素(非HDR)或192位/像素(HDR)。
相機不使用HDR時,Emission+lighting緩衝區(RT3)以對數方式編碼,以提供比ARGB32紋理通常可能的更大的動態範圍。
注意,相機使用HDR渲染時,沒有爲Emission +光照緩衝區(RT3)創建單獨的渲染目標; 相反,Camera渲染的渲染目標(即傳遞給圖像效果的渲染目標)用作RT3。
G-Buffer Pass:
渲染每個Gameobject一次,漫反射和鏡面反射顏色,表面平滑度,世界空間法線和發射+環境+反射+光照貼圖渲染爲g緩衝區紋理。g-buffer紋理被設置爲全局着色器屬性,以供稍後訪問着色器
Lighting Pass:
照明通過基於g緩衝區和深度計算照明。照明是在屏幕空間中計算的,因此處理時間與場景複雜度無關。燈光會被添加到emission 緩衝區中。
不穿過相機近平面的點光源和聚光燈會渲染爲3D形狀,並啓用Z緩衝區對場景的測試,這使得部分或完全遮擋得點光燈和聚光燈非常塊快得渲染。穿過近平面得定向燈和點/聚光燈呈現爲全屏四邊形。
如果燈光開啓了陰影,那麼它們也會在此過程中渲染並應用,陰影並不是“免費”出現的。需要渲染陰影投射器並運用更加複雜的光線着色器。
唯一可用的照明模型是 Standard,如果需要不同的模型,可以修改光照通道着色器,將內置着色器中的Internal-DeferredShading.sharder 文件的修改版本放入Asset/Resources文件夾中,然後在Edit/Project Settings/Graphics 窗口中將“Deferred”修改爲“Custom Shader”,然後更改這個在使用的着色器選項。
Legacy Deferred Lighting Rendering Paht(舊版延遲光照渲染路徑):
與Deferred shadering 相似,從Unity5.0 版本以後被認爲是傳統功能,因爲他不支持某些渲染功能(如標準着色器,反射探測器等)。
使用延遲光照時,Unity中的渲染過程會分爲3步:
1.Base Pass:渲染對象以生成具有深度,法線和鏡面反射功率的屏幕空間緩衝區。
2.Light Pass:使用前面生成的緩衝區用於計算照明到另一個屏幕空空間緩衝區(唯一可用的照明模型爲Blinn-Phong)。
3.Final Pass:再次渲染對象。它們獲取計算出的光照,將其與顏色紋理相結合,並添加任何環境/發光照明。
Vertex Lit Rendering Path (頂點照明路徑):
Vertex Lit路徑通常在一次通過中渲染每個對象,並在對象頂點出計算所有光源的光照。
Vertex Lit是最快的渲染路徑,並且具有最廣泛的硬件支持(不使用與控制檯)。
由於所有的光照都是在頂點級別計算的,因此此渲染路徑不支持大多數逐像素效果:不支持陰影,法線貼圖,cookie和非常細膩的鏡面高光。