unity Shader複雜光照

一、渲染路徑

1、unity支持的渲染路徑:前向渲染路徑(Forword)、延遲渲染路徑(Deferred)、頂點照明渲染路徑(Vertex Lit)。

2、可以在項目上設置、也可以在攝相機上設置或者在Shader上設置,在shader上利用LightMode標籤實現。

3、Pass的LightMode標籤支持的渲染路徑設置選項。

LightMode標籤支持的渲染路徑設置選項
標籤名 描述
Always 不管使用那種渲染路徑,該pass總是會被渲染,但不計算任何光照
ForwardBase 用於前向渲染,該Pass會計算環境光、最重要的平行光、逐頂點/SH光源和Lightmaps
ForwardAdd 用於前向渲染,該Pass會計算額外的逐像素光源,每個Pass對應一個光源
Deferred 用於延遲渲染,該pass會渲染G緩存(G-buffer)
ShadowCaster 把物體的深度信息渲染到陰影映射紋理(shadowmap)或一張深度紋理中
PrepassBase 用於遺留的延遲渲染,該pass會渲染法線和高光反射的指數部分
PrepassFinal 用於遺留的延遲渲染,該pass通過合併紋理、光照和自發光來渲染得到最後的顏色
Vertex、VertexMRGBM和VertexLM 用於遺留的頂點照明渲染

注意:在渲染設置的時候,我們除了設置Pass的標籤外,還要正確使用#pragma multi_compile_fwdbase這樣的編譯指令。實驗表明只有分別爲Bass Pass和Additional Pass設置#pragma multi_compile_fwdbase和#pragma multi_compile_fwdadd編譯指令,我們纔可以在相關的Pass中得到正確的光照變量,例如光照衰減值等。

 

4、前向渲染路徑

①原理:每進行一次完整的前向渲染,我們需要渲染該對象的渲染圖元,並計算兩個緩衝區的信息:一個是顏色緩衝區,一個是深度緩衝區,我們利用深度緩衝來決定一個片元是否可見,如果可見就更新顏色緩衝區中的顏色值。

②Unity中前向渲染路徑有3種處理光照的方式:逐頂點處理、逐像素處理、球諧函數處理。一個光源使用哪種處理模式取決於它的類型和渲染模式。

③Unity會根據場景中各個光源的設置以及這些光源對物體的影響程度對這些光源進行一個重要度排序。規則如下:

Ⅰ、場景中最亮的平行光總是按逐像素處理的

Ⅱ、渲染模式被設置爲Not Important的光源,會按逐頂點或者SH處理

Ⅲ、渲染模式設置爲Important的光源,會按逐像素處理

Ⅳ、如果根據以上規則得到的逐像素光源數量小於Quality Setting中的逐像素光源數量(Pixel Light Count),會有更多的光源以逐像素的方式進行渲染。

④Unity中前向渲染的兩種Pass

5、頂點照明渲染路徑

它是對硬件配置要求最少、運算性能最高,但得到效果最差的一種類型,它不支持逐像素才能得到的效果,它僅僅是前向渲染路徑的一個子集。

6、延遲渲染路徑

①原理:延遲渲染主要包含兩個Pass,在第一個Pass中,我們不進行任何光照計算,僅是計算那些片元可見的,這主要通過深度緩衝技術實現,當我們發現一個片元是可見的,我們就把它的信息存儲到G緩衝區中。然後,在第二個Pass中,我們利用G緩衝區的各個片元信息,進行真正的光照計算。

②缺點

不支持真正的抗鋸齒(anti-aliasing)功能

不能處理半透明物體

對顯卡有一定要求

7、三個渲染路徑更詳細記錄請看鏈接:shader四大解釋

二、光源類型

1、unity一共支持四種光源類型:平行光、點光源、聚光燈和麪光燈。並且在在Shader中常用的光源屬性有光源的位置、方向、顏色、強度以及衰減。

三、unity的陰影

1、在實時渲染中,最常用的一種名爲Shadow Map的技術,這種技術它會首先把攝像機的位置放在於光源重合的位置上,那麼場景中該光源的陰影區域就是那些攝像機看不到的地方,而unity就是使用的這種技術。

2、陰影實現流程

Ⅰ、讓物體接收陰影

簡單總結一下物體接收來自其他物體的陰影,以及它向其他物體投射陰影是兩個過程。

①如果我們想要一個物體接收來自其他物體的陰影,就必須在Shader中對陰影映射紋理(包括屏幕空間的陰影圖)進行採樣,把採樣結果和最後的光照結果相乘來產生陰影效果。

②如果我們想要一個物體向其他物體投射陰影,就必須把該物體加入到光源的陰影映射紋理的計算中,從而讓其他物體在對陰影映射紋理採樣時可以得到該物體的相關信息。在Unity中,這個過程是通過爲該物體執行LightMode爲ShadowCaster的Pass來實現的,如果使用了屏幕空間的投影映射技術,Unity還會使用這個Pass產生一張攝像機的深度紋理。

③讓物體接收陰影:在前向渲染中,宏SHADOW_COORDS就是聲明瞭一個名爲_ShadowCoord的陰影紋理座標變量。而TRANSFER_SHDOW的實現會根據平臺不同而有所差異。如果當前平臺可以使用屏幕空間的陰影映射技術,TRANSFER_SHADOW會調用內置的ComputeScreenPos函數計算_ShadowCoord;如果該平臺不支持屏幕空間的陰影映射技術,就會使用傳統的陰影映射技術,TRANSFER_SHADOW會把頂點座標從模型空間變換到光源空間後存儲到_ShadowCoord中。然後SHADOW_ATTENUATION負責使用_ShadowCoord對相關的紋理進行採樣,得到陰影信息。

注意,當關閉了陰影后,SHADOW_COORDS和TRANSFER_SHDOW實際沒有任何作用,而SHADOW_ATTENUATION會直接等同於數值1。

Ⅱ、讓物體投射陰影(對於非透明物體),我們把Fallback設爲VertexLit就可以得到正確的陰影。

對於使用透明物體我們要小心設置物體的Fallback也可以得到算是理想的效果,

對於使用透明度測試實現透明的物體,Fallback設置爲Transparent/Cutout/VertexLit實現透明度陰影

對於透明度混合來講,在unity中,所有內置的半透明Shader是不會產生任何陰影效果的,但是可以將Fallback設置爲不透明物體使用的VertexLit,Diffuse。這樣unity就會在它的Fallback中找到一個陰影投射Pass,但此時陰影不會穿透半透明物體。

3、統一管理關照衰減和陰影

UNITY_LIGHT_ATTENUATION是unity內置的用於計算關照衰減和陰影的宏,我們可以在內置的AutoLight.cginc裏找到它的相關聲明。它接收3個參數,它會將光照衰減和陰影值相乘後的結果存儲到第一個參數中。第二個參數是結構體v2f,這個是傳遞給SHADOW_ATTENUATION,用來計算陰影值。第三個參數是世界空間的座標,這個參數會用於計算光源空間下的座標,再對光照衰減紋理採樣來得到光照衰減。

在AutoLight.cginc中UNITY_LIGHT_ATTENUATION聲明的時候,Unity針對不同的光源類型、是否啓用cookie等不同情況聲明瞭多個版本的UNITY_LIGHT_ATTENUATION。

4、透明物體陰影

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章