目錄編程 |
1 方向光陰影c# 1.1 配置陰影api 1.2 渲染陰影數組 1.3 陰影距離微信 1.4 調查陰影編輯器 1.5 鉗位陰影瓦片ide 1.6 老是使用裁切函數 1.7 基於距離進行陰影裁減flex 2 級聯陰影貼圖編碼 2.1 級聯數量 2.2 級聯分割 2.3 只對主方向光使用級聯 2.4 重用代碼 2.5 渲染級聯 2.6 採樣陰影貼圖 2.7 選擇正確的級聯 |
本文重點:
一、支持多個定向光陰影
二、控制陰影距離
三、定義分離的主光源
四、渲染和採樣一個級聯陰影貼圖
五、讓剔除球體生效
這是涵蓋Unity的可腳本化渲染管線的教程系列的第五部分。此次,咱們將添加對定向陰影的支持。
本教程是CatLikeCoding系列的一部分,原文地址見文章底部。「原創」標識意爲原創翻譯而非原創教程。
本教程使用Unity 2018.3.0f2製做。
(4個使用了陰影的定向光,一個帶有級聯)
1 方向光陰影
從概念上講,定向燈與聚光燈沒有什麼不一樣。它們是相同的,只是無限遠。咱們對聚光燈陰影使用的方法也適用於它們,但進行了一些調整。咱們將加強管線,使其支持能夠投射陰影的定向光和聚光燈的混合。
1.1 配置陰影
當前,ConfigureLights僅在聚光燈下處理陰影數據。可是當咱們也支持定向陰影時,同一段代碼須要使用兩次。所以,將相關代碼複製到一個單獨的方法中,根據燈光索引和陰影燈光進行工做,而後返回陰影數據。
在ConfigureLights中爲聚光燈使用新方法。
並將其用於定向燈。
因爲渲染定向陰影貼圖時存在一些差別,所以,咱們在此處表示正在處理定向光。能夠經過將陰影數據的Z份量用做標誌來作到這一點。
1.2 渲染陰影
此時,咱們在陰影貼圖中爲定向光保留了圖塊,但它仍然沒有用,由於RenderShadows正在爲聚光燈計算其矩陣。咱們只能將ComputeSpotShadowMatricesAndCullingPrimitives用於聚光燈,而必須使用其餘方法來計算定向光的矩陣。
首先,從檢查是否有有效陰影中拉出對ComputeSpotShadowMatricesAndCullingPrimitives的調用。這樣能夠更輕鬆地對定向光進行不一樣的處理。
接下來,若是陰影數據指示咱們有定向光,則改成調用ComputeDirectionalShadowMatricesAndCullingPrimitives。該方法具備更多參數,由於它容許咱們使用陰影級聯,在此咱們再也不作。咱們提供的第一個參數是光指數,其次是級聯指數和級聯數量。如今不使用級聯,索引爲零,計數爲1。以後是一個三份量向量來定義級聯拆分,咱們將使用(1,0,0)。接下來是圖塊大小(整數),而後是靠近平面的陰影值,最後是矩陣和拆分數據輸出。
這爲咱們提供了正確的方向陰影矩陣。除此以外,分割數據還包含有效的剔除範圍。這是一個包圍全部須要渲染以建立有效方向陰影貼圖的對象的球體。這對於定向陰影頗有用,與聚光燈不一樣,它們會影響一切。經過將剔除球分配給陰影設置的分割數據,咱們可使用剔除球來減小必須渲染到陰影貼圖中的形狀數量。
聚光燈沒有有效的剔除球體,可是因爲沒有效果,咱們仍然能夠對其進行分配。所以,咱們沒必要在此處區分光源類型。
1.3 陰影距離
如今,咱們應該爲定向光指定有效的陰影貼圖,可是它們彷佛是空的,除了可能有一個小點以外。這是由於貼圖必須覆蓋攝像機能夠看到的全部內容,默認狀況下,最多能夠看到1000個單位,而且由攝像機的遠平面控制。不管是否實際存在幾何圖形,都須要覆蓋該區域,所以貼圖會擁有一個很是大的比例尺。大幅減小相機的遠平面距離將最終使陰影出現。
陰影的渲染距離與相機的遠平面無關,這只是默認行爲。存在一個陰影距離參數,該距離控制渲染陰影的距離。陰影距離一般比相機的遠平面小得多。這既限制了必須渲染的陰影數量,又使定向陰影貼圖覆蓋較小的區域。
向MyPipeline添加shadow distance字段,該字段是經過其構造函數設置的。從相機中將其提取後,再將其分配給剔除參數。因爲渲染陰影超出相機可見的範圍沒有意義,所以請使用陰影距離和相機遠平面中的最小值。
將陰影距離的配置選項添加到MyPipelineAsset,併爲其指定一個合理的默認值,例如100。
(陰影距離設置爲10)
1.4 調查陰影
一旦陰影距離已充分減少,定向陰影就會出現了。如今,讓咱們以很小的距離(例如10)工做。要得到對貼圖所覆蓋內容的良好印象,請將燈光的陰影誤差設置爲零,並使用大平面做爲地面。從單個定向燈開始。
(方向陰影 誤差設置爲0)
因爲零誤差,以及地面上的自陰影,咱們能夠大體看到陰影貼圖覆蓋的區域。與聚光燈陰影不一樣,定向陰影貼圖隨攝影機一塊兒移動。一樣,陰影貼圖的邊緣仍然能夠超出其範圍來影響場景。發生這種狀況是由於咱們最終採樣超出了地圖的邊緣,從而有效地將其邊緣擴展到無窮大。當咱們有一個以上的陰影光時,這種拉伸就消失了,由於而後使用剪切清理每一個瓦片的邊緣。
(2個陰影貼圖瓦片,一個定向光和一個聚光燈)
可是,當有多個圖塊時,咱們可能最終會超出定向圖塊的邊界進行採樣,並最終從錯誤的圖塊進行採樣。瓦片越多,效果越差。
(兩個定向光 一個聚光燈 產生的陰影)
1.5 鉗位陰影平鋪
定向陰影貼圖很麻煩,由於不管覆蓋什麼區域,都須要在各處採樣。解決方案是將陰影採樣固定在圖塊上。這是經過將陰影位置轉換爲0–1範圍,縮放並偏移到正確的圖塊以前,將其陰影位置鉗位來完成的。不用鉗位的話,能夠在MyPipeline中計算整個變換矩陣,可是如今咱們必須將圖塊變換步驟移至着色器。
切片縮放須要切片比例,所以咱們必須將其發送到着色器。讓咱們爲此添加一個全局陰影數據向量,也可使用它稍後存儲更多的東西。將其命名爲_GlobalShadowData並跟蹤其着色器標識符。
將平鋪比例尺放在此向量的第一個份量中,並將其設置在RenderShadows中。
着色器還須要知道全部圖塊的偏移量。咱們能夠將它們存儲在陰影數據向量的ZW份量中。
以後,刪除與圖塊矩陣的乘法。
在着色器端,將全局陰影數據矢量添加到陰影緩衝區。
在ShadowAttenuation中,在透視分割後鉗制陰影位置的XY座標。以後,應用平鋪轉換。
(沒有錯位的陰影了)
透視分區對方向陰影是否有效?
不須要,由於定向陰影貼圖使用正交投影。陰影位置的W份量始終爲1。可是,因爲咱們混合了方向燈貼圖和聚光燈貼圖,所以咱們老是執行除法。
1.6 老是使用裁切
當使用多個圖塊時,咱們解決了陰影問題,可是當只有一個方向性陰影貼圖處於活動狀態時,咱們仍然獲得了拉伸的陰影貼圖邊緣。經過始終在RenderShadows中進行裁切來解決該問題。
(單獨的方向光 帶有裁切)
1.7 基於距離進行陰影裁減
儘管陰影距離是基於視距的,但陰影超出範圍並不會當即消失。這是由於陰影貼圖覆蓋了拉伸的立方區域。若是部分區域落在陰影距離內,則將徹底渲染它們。方向陰影貼圖隨相機移動,而且其形狀最適合陰影距離,所以它們的匹配度很是好。相反,聚光燈陰影體積固定在其光線上。若是即便它們的體積的一小部分都在範圍內,則將徹底渲染它。結果是單個聚光燈的全部陰影一塊兒出現和消失。
有時我會獲得聚光燈下陰影的奇怪剪裁?
Unity 2018.3中存在一個錯誤,該錯誤會致使陰影距離邊緣處的聚光燈陰影發生奇怪的陰影修剪。當使用很是短的陰影距離時,這可能會很嚴重。在照相機移動過程當中,這表現爲閃爍或不正確的裁剪。
經過在配置的陰影距離處修剪陰影,可使陰影的消失更加均勻。爲此,咱們必須將陰影距離傳遞給着色器。咱們能夠將其放在全局陰影數據向量的第二個份量中。當咱們使用它進行裁剪時,咱們能夠經過比較平方距離就足夠了,所以能夠存儲平方距離。
爲了在場景中只有主光源時也可使用此功能,請在RenderCascadedShadows中設置距離。
咱們還須要知道相機在着色器中的位置。設置攝像機時,Unity已經提供了此信息。咱們要作的就是添加一個帶有float3 _WorldSpaceCameraPos變量的UnityPerCamera緩衝區。
建立一個方便的DistanceToCameraSqr函數,該函數會佔據世界位置並將距離的平方返回給相機。
在ShadowAttenuation中調用此功能,檢查咱們是否超出陰影距離,若是是,則跳過採樣陰影。在現有的檢查中使用它做爲附加條件,這樣咱們就不會獲得額外的分支。
如今,全部陰影都在相同距離處被切除,而不只僅是忽然出現或消失。
(距離clamp,陰影距離15,沒有誤差VS有誤差(bias))
咱們不能使陰影平滑消失嗎?
能夠經過添加漸變範圍並使用線性插值,平滑步長或其餘轉換函數來實現。
2 級聯陰影貼圖
陰影貼圖的侷限性在於它們是紋理,所以具備紋理像素密度。若是紋理像素在視覺上最終過大,則能夠增長陰影貼圖的分辨率,但這是有限制的。對於僅覆蓋較小區域的聚光燈,它能夠很好地工做,可是定向燈具備無限的範圍。你可能獲得這樣一個視圖,其中遠處的陰影看起來很好,可是附近的陰影太塊狀了。這稱爲透視鋸齒。
(透視鋸齒)
咱們須要較高分辨率的附近陰影,可是距離較遠的陰影很好。理想狀況下,咱們能夠根據距離使用不一樣的分辨率。該問題的解決方案是爲同必定向光渲染多個陰影貼圖。每一個貼圖具備相同的大小,但使用不一樣的陰影距離。而後,咱們將爲每一個片斷選擇最佳的貼圖。這樣,就能夠在附近得到更高的分辨率,而在更遠的地方得到更低的分辨率,這是對像素的更明智的使用。這些貼圖中的每個都稱爲陰影級聯。
2.1 級聯數量
對於陰影級聯的數量,Unity始終提供三個選項:零,兩個或四個。咱們將支持相同的選項。將自定義ShadowCascades枚舉配置選項添加到MyPipelineAsset以使其可配置,默認值爲4。
將陰影選項移至批處理和實例化選項下方,以備未來添加。
(使用4個級聯)
2.2 級聯分割
Unity還容許你指定級聯相對於陰影距離的分佈方式。經過將整個陰影範圍分爲兩部分或四部分來完成。對於兩個級聯,單個值控制拆分發生的位置。在四個級聯的狀況下,三個分割值存儲在一個向量中。咱們將再次使用與Unity相同的方法,並使用與輕量級渲染管線相同的默認值。
可是Unity不會直接公開這些值。而是顯示了一個特殊的GUI控件,使您能夠調整級聯區域。咱們將使用相同的GUI,所以經過將HideInInspector屬性附加到拆分字段來隱藏拆分字段。
建立一個自定義編輯器以顯示級聯拆分GUI。咱們將建立一個很是基本的示例。將其腳本的資產文件放在Editor文件夾中,使其跟蹤三個相關屬性,並繪製默認檢查器。咱們還須要使用UnityEditor.Experimental.Rendering命名空間,由於它包含級聯拆分GUI的代碼。
自定義編輯器如何工做?
簡而言之,你能夠將腳本放在「Editor」文件夾中,使用UnityEditor命名空間,並使它繼承自Editor 。爲其提供CustomEditor屬性,以指示應使用哪一種類型。而後,重寫OnInspectorGUI方法以繪製其檢查器。能夠經過調用DrawDefaultInspector來繪製默認檢查器。
每一個Editor都有一個serializedObject屬性,該屬性表示正在編輯的內容。能夠經過在其上調用FindProperty來從中提取字段,這將返回SerializedProperty引用。這一般是在OnEnable方法中完成的。
使用CoreEditorUtils.DrawCascadeSplitGUI方法繪製所需的內容。它的設計有點怪異。這是一種通用方法,能夠在浮點數或向量上使用。第一個用於兩分割,第二個用於四分割。相關的序列化屬性必須做爲參考參數傳遞。
繪製默認檢查器後,使用開關肯定咱們必須顯示的GUI。咱們能夠爲此訪問shadowCascades屬性的enumValueIndex。它爲咱們提供了所選枚舉選項的索引,而不是實際的枚舉值。因此它是0、1或2,而不是0、2或4。在第一種狀況下,咱們能夠中止,而在另外兩種狀況下,咱們能夠調用適當的方法。以後,咱們必須在序列化的對象上調用ApplyModifiedProperties,以便將用戶的更改應用於咱們的資產。
(級聯分割GUI顯示4個級聯)
當我編輯Split時,爲何天空盒在場景窗口中消失了?
這是視覺BUG。在編輯器中執行其餘操做後刷新場景窗口時,它會自行修復。
MyPipeline只須要知道要使用多少級聯以及拆分值是多少。咱們可使用單個3D向量存儲兩個和四個級聯的拆分數據。添加必填字段和構造函數參數。
當MyPipelineAsset調用管線的構造函數時,哪怕只有兩個級聯,也必須提供一個分割向量。在兩個級聯的狀況下,單個分割值成爲第一個,而其餘兩個保持零。
2.3 只對主方向光使用級聯
咱們不支持全部定向光的級聯陰影貼圖。每盞燈繪製多張貼圖並找出要採樣的東西並不便宜。所以,咱們將自身限制爲具備級聯陰影貼圖的單個定向光。這將是場景中陰影最明亮的定向光。咱們將其稱爲主要光源。全部其餘定向光僅得到一個陰影貼圖。
主方向燈始終是可見光列表中的第一個元素。咱們能夠肯定第一個光源是否符合ConfigureLights中的條件。若是它是定向的,具備陰影,具備正的陰影強度而且啓用了陰影級聯,則咱們有一個主光源。使用布爾字段跟蹤此事實。
咱們不會嘗試將陰影級聯貼圖與全部其餘陰影貼圖配合在同一紋理中。若是存在帶陰影的多個燈光,那會使它們過小。所以,當遇到主光源時,請減小陰影圖塊的數量。
所以,若是存在主光源,則必須跳過RenderShadows中的第一個光源。
咱們將陰影級聯渲染爲平鋪到單獨的陰影貼圖,將其命名爲_CascadedShadowMap。爲其添加標識符和字段,並確保將其與其餘陰影貼圖一塊兒釋放。
2.4 重用代碼
渲染級聯陰影貼圖的渲染與咱們已經在作的陰影渲染類似,但差別很大,須要使用本身的方法。可是,這兩種方法的許多代碼都是相同的,所以讓咱們將這些位移到單獨的方法中。
首先是設置陰影的渲染目標。兩種方法都相同,咱們只須要跟蹤具備不一樣字段的渲染紋理便可。所以,將該代碼放在返回對紋理的引用的方法中。無需添加其餘陰影配置選項,咱們將對兩個貼圖使用相同的大小。若是要爲級聯陰影貼圖的大小包括一個單獨的控件,則能夠在此方法中添加一個size參數。
其次是配置陰影圖塊。肯定偏移量,設置視口和進行剪裁均可以放在一塊兒。瓦片偏移能夠做爲2D向量返回。
第三,計算陰影世界矩陣也能夠採用其本身的方法。將視圖和投影矩陣定義爲參考參數,所以不須要複製它們。一樣,將世界陰影矩陣做爲輸出參數。
最後,調整RenderShadows,以便利用這些新方法。
2.5 渲染級聯
級聯的世界陰影矩陣須要存儲在它們本身的數組中,所以要爲其添加標識符和字段。因爲咱們最多有四個級聯,所以數組的長度爲四個。
建立一個新的RenderCascadedShadows,它能夠做爲RenderShadows的副本開始。最終變得更簡單,由於咱們沒必要擔憂聚光燈,只須要使用第一個燈光便可。咱們沒必要處理每一個光的陰影數據,而且級聯始終有效。咱們有兩個或四個級聯,所以老是將地圖切成四個圖塊。
如今,當調用ComputeDirectionalShadowMatricesAndCullingPrimitives時,咱們將0用做燈光索引,將插值器用做級聯索引。咱們還爲它提供了實際的級聯數量和拆分向量。
最後,咱們將再次烘焙世界到陰影矩陣中的圖塊轉換。確保咱們留在圖塊邊界內是在着色器中選擇正確的層疊的一部分。
若是有主光源,請在ConfigureLights以後調用此方法。
如今,咱們可使用1,2或0個渲染紋理結束。若是隻有主光源,則咱們僅渲染到級聯陰影貼圖。若是還有帶有陰影的其餘光源,那麼咱們也將渲染到常規陰影貼圖。或者咱們有陰影但沒有主光源,在這種狀況下,咱們僅渲染到常規陰影貼圖。幀調試器會將兩個「Render Shadows」部分合併爲一個。
(渲染到兩個陰影貼圖)
若是經過幀調試器檢查級聯陰影貼圖,你會看到它包含四個圖塊。瓦片中可見的內容取決於陰影距離和級聯拆分。在默認的四個級聯拆分的狀況下,須要大的陰影距離,以便任何東西出如今第一個級聯中。
(級聯陰影貼圖)
2.6 採樣陰影貼圖
要使用着色器中的級聯陰影貼圖,咱們須要作一些事情。首先,咱們必須知道貼圖正在使用中,能夠經過着色器關鍵字進行控制。咱們使用兩個來區分硬和軟級聯陰影,避免在着色器中出現分支。
接下來,咱們還須要知道貼圖的大小和陰影強度。雖然咱們可使用_ShadowMapSize,但仍是使用單獨的_CascadedShadowMapSize向量,以便着色器支持單獨的大小。
在RenderCascadedShadows的末尾設置這些值和關鍵字。
當未調用RenderCascadedShadow時,也請禁用級聯的陰影關鍵字。
爲級聯的shadow關鍵字向Lit着色器添加單個multi-compile指令。共有三個選項:no, hard, soft 級聯陰影。
以後,將所需的變量添加到陰影緩衝區,並定義級聯的陰影貼圖紋理和採樣器。
讓咱們經過添加一個布爾參數來指示是否要對級聯進行採樣,使HardShadowAttenuation與兩個貼圖一塊兒使用,默認值爲false。使用它來決定使用哪一種紋理和採樣器。咱們將對級聯參數進行硬編碼,所以它不會致使着色器分支。
給予SoftShadowAttenuation相同的處理。在這種狀況下,選擇正確的陰影貼圖大小便可。咱們能夠在此處調用HardShadowAttenuation,所以咱們沒必要再次編寫相同的代碼。
如今添加一個CascadedShadowAttenuation函數,它是ShadowAttenuation的簡單版本。若是沒有級聯,則衰減始終爲1。不然,計算陰影位置並獲取硬陰影或軟陰影衰減並應用陰影強度。在這一點上,咱們將不會根據距離裁剪陰影。
首先始終使用第三個陰影級聯貼圖,所以使用2索引_WorldToShadowCascadeMatrices數組。這樣一來,假設你使用的是四個級聯,最有可能在至關大的區域中看到至少一些陰影。第四個級聯覆蓋最大的區域,但分辨率可能過低,以至附近的陰影很難看清。
接下來,添加一個單獨的MainLight函數以照顧主光源。它的做用與DiffuseLight相同,但僅限於索引爲零的定向光,它的陰影依賴於CascadedShadowAttenuation。
若是存在級聯陰影,則將主光添加到LitPassFragment中的漫射光。
(主光源 2次)
如今會顯示主光的級聯陰影,可是同一燈光在光循環中添加2次,這是不正確的。咱們不能簡單地跳過光循環的第一個索引,由於不能保證主光對於每一個對象都是最重要的光。咱們要麼在循環中添加另外一個着色器分支,要麼在渲染以前從可見光列表中消除主光源。能夠在ConfigureLight中作到這一點,並限制燈光的數量。反作用是,當主光源處於活動狀態時,這還將每一個對象的最大像素光增長到五個。
(主光源 只有1次)
從列表中消除主光源意味着咱們在使用級聯陰影的每一幀中都調整可見光。當前,這還意味着每一個此類幀都會分配一個臨時內存。咱們必須忍受這一點,直到得到一個變體GetLightIndexMap方法,該方法不會在每次調用時分配新的數組。
2.7 選擇正確的級聯
如今,咱們有一個具備級聯陰影貼圖的功能性主光源,可是咱們始終使用相同的級聯。第三個級聯適用於相距較遠的陰影,但不適用於附近的陰影。相比之下,第二個級聯在附近要好得多,但不會覆蓋那麼大的區域。
(第二個級聯)
Unity使用級聯拆分將陰影空間劃分爲級聯。它使用剔除球來定義每一個級聯的區域。每一個連續球體都有較大的半徑。它們的位置也各不相同,由於它們的位置儘量地最佳,以覆蓋所需的儘量少的場景。爲了肯定使用哪一個級聯,咱們必須找出每一個片斷位於哪一個剔除球內。
將剔除球發送到着色器。經過數組執行此操做最方便。爲此,向MyPipeline添加一個標識符和字段。每一個球體均由4D向量描述。XYZ份量定義其位置,而W份量定義其半徑。
咱們已經檢索了RenderCascadedShadows內部每一個級聯的剔除範圍。能夠簡單地將它們複製到數組,而後將其發送到着色器。並且,因爲咱們只須要檢查碎片是否位於球體內,可使用平方距離進行比較,對存儲的半徑求平方便可。
在着色器一側,將剔除球陣列添加到陰影緩衝區。
們添加一個方便的方法,使用其索引做爲參數來檢查世界位置是否落在給定的剔除球內。稍後咱們將對結果進行一些數學運算,所以將其做爲浮點數返回。
在全部四個剔除球的CascadedShadowAttenuation中調用該函數。對於每一個球體,當球體包含點時結果爲1,不然爲零。這些值用做指示哪些球有效的標誌。在肯定級聯索引以前,將它們放入有序的float4變量中。
若是點位於一個球體內,那麼它也位於全部較大的球體內。所以,咱們能夠獲得五種不一樣的標誌配置:(1,1,1,1),(0,1,1,1),(0,0,1,1),(0,0,0,1) 或(0,0,0,0)。經過將標誌求和併除以四,咱們可使用它來可視化級聯。這能夠經過取標誌與(?,?,?,?)的點積來完成。
(可視化級聯 調整拆分以使其所有可見)
咱們須要使用第一個有效的級聯,所以必須在設置第一個級聯以後清除全部標誌。第一個標誌始終是好的,可是若是設置了第一個,則應清除第二個標誌。設置第二個時應清除第三個。一樣直到第四個。能夠經過從YZW中減去XYZ份量並使結果飽和來作到這一點。若是咱們將結果的點積與(0,1,2,3)相乘,那麼咱們將得出最終的級聯索引。轉換過程以下:
當至少一個剔除球包含該點時,此方法正確工做。可是,當一個點位於全部球體以外時,咱們最終獲得零,這會從第一個級聯中錯誤地採樣的。Unity在這裏使用的一個技巧是爲第五個不存在的級聯提供額外的世界到陰影矩陣。這是一個零矩陣,它將陰影位置設置爲近平面,所以永遠不會產生陰影。咱們能夠經過在MyPipeline中的worldToShadowCascadeMatrices數組中添加第五個元素來實現。
可是,當使用反向Z緩衝區時,咱們必須將陰影位置Z座標改成1。咱們能夠經過在構造函數中將虛擬矩陣的m33字段設置爲1來實現。
增長着色器中矩陣陣列的大小以進行匹配。像之前同樣,若是你已經在長度爲4時編譯了着色器,則須要從新啓動Unity。
如今咱們必須包括(0,0,0,0)→4轉換,能夠經過從4開始並用(4,3,2,1)減去獨立標誌的點積來完成。
(採樣正確的級聯)
咱們能夠混合級聯嗎?
像Unity的管線同樣,咱們直接從一個級聯切到下一個。這會致使級聯之間的不連續,其中紋理像素大小會忽然改變。你能夠在相鄰級聯之間進行插值的過渡區域中添加一個過渡區域,但這須要找到兩個級聯索引,一個混合因子並使陰影樣本數量加倍。
因爲剔除球不與相機和陰影距離對齊,所以級聯陰影不會在與其餘陰影徹底相同的距離處被切除。有時更近,有時更遠,它們仍然能夠忽然出現或消失。咱們也能夠經過在CascadedShadowAttenuation中檢查陰影距離來同步它們。
Unity能夠經過screen-space pass來採樣級聯的陰影貼圖嗎?
會,Unity添加了一個單獨的屏幕空間通道,當使用級聯陰影時,該通道將渲染到另外一個紋理。它完成了與咱們相同的操做,一次完成了整個顯示。而後,它在每一個片斷的lit forward pass採樣中對所得的陰影數據進行採樣。兩種方法都是有效的。添加屏幕空間通道最終會完成相同的工做,只是要繞行。逐片斷是最簡單的方法,所以我在本教程中選擇了它。
使用單獨的全屏pass的原理是,每一個顯示紋理像素對級聯進行採樣的速度更快。當存在大量overdraw時,這多是正確的,在這種狀況下,咱們可能最終對每一個片斷採樣級聯貼圖不止一次。能夠經過添加僅深度的通道來填充深度緩衝區,從而消除不透明的overdraw,從而緩解這種狀況。屏幕空間方法始終只須要執行一次深度操做便可檢索片斷深度。
在Unity的舊式渲染管線的狀況下,經過屏幕空間的另外一個緣由是它執行了更高質量的軟陰影過濾。但這對於輕量級渲染管線而言並不是如此,該管線對全部陰影採樣使用相同的代碼。
哪一種方法最好?你能夠爲目標平臺配置三個選項:每一個片斷,每一個片斷僅深度,或屏幕空間僅深度。
下一篇,介紹透明度。
往期回顧:
![](http://static.javashuo.com/static/loading.gif)
Unity可編程渲染管線系列(四)聚光燈陰影(陰影貼圖)
![](http://static.javashuo.com/static/loading.gif)
Unity可編程渲染管線系列(三)光照(單通道 正向渲染)
![](http://static.javashuo.com/static/loading.gif)
Unity可編程渲染管線系列(二)自定義着色器(HLSL和核心庫)
![](http://static.javashuo.com/static/loading.gif)
Unity可編程渲染管線系列(一)自定義管線(控制渲染)
![](http://static.javashuo.com/static/loading.gif)
新的征程從受權開始
本文翻譯自 Jasper Flick的系列教程
原文地址:
https://catlikecoding.com/unity/tutorials
![](http://static.javashuo.com/static/loading.gif)
本文分享自微信公衆號 - 壹種念頭(OneDay1Idea)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。