3D 燈光與陰影
前言
光源發出燈光,燈光會與材質相混合,產生可見的結果。場景可以有很多不同型別的光源:
來自材質本身的自發光顏色(但是無法影響附近的物件,除非進行了烘焙,或者啟用了螢幕空間間接光照)。
燈光節點:DirectionalLight3D、OmniLight3D、SpotLight3D。
Environment 或 反射探針 中的環境光。
全域光照(LightmapGI、VoxelGI、SDFGI)。
自發光是材質的屬性。更多相關內容見 標準 3D 材質與 ORM 3D 材質 教學。
也參考
您可以透過使用 3D 燈光與陰影示範專案 來比較各種類型燈光的實際效果。
燈光節點
燈光節點有三種:DirectionalLight3D、OmniLight3D、SpotLight3D。讓我們來看看燈光的通用參數:
每個屬性都有特定的功能:
Color: 發光的基礎顏色。
Energy: 能量乘數。這對於使燈光飽和或使用 高動態範圍光照 非常有用。
Indirect Energy: 間接能量。用於間接光(反彈的光)的次級乘數。適用於 使用光照貼圖全域光照、VoxelGI 和 SDFGI。
Volumetric Fog Energy: 體積霧能量。用於體積霧的次級乘數。僅在啟用體積霧時有效。
Negative(負光):該光源將改為減色而非加色。有時可以用來手動彌補某些過暗的角落。
Specular: 鏡面反射。影響受此光影響的物體中鏡面反射斑點的強度。值為零時,該光變為純漫反射光。
Bake Mode: 設定燈光的烘焙模式。見 使用光照貼圖全域光照。
Cull Mask(剔除遮罩):只會影響下方已選圖層中的物件。注意,被此遮罩排除的物件仍會投射陰影。如果你不希望這些物件投射陰影,請將 GeometryInstance3D 上的 Cast Shadow 屬性調整為適當的值。
也參考
如果想要使用實際物理單位來設定燈光的強度與色溫,請參閱 物理燈光與相機單位。
燈光數量限制
當使用 Forward+ 算繪器時,Godot 採用*叢集*方法來進行即時光照。你可以加入任意數量的燈光(只要效能允許)。然而,目前攝影機畫面中預設限制為 512 個*叢集元素*。叢集元素包含全向光、聚光燈、decal 或 reflection probe。這個限制可以透過【專案設定 > 算繪 > 限制 > 叢集產生器】中的 Max Clustered Elements 提高。
當使用 Mobile 算繪器時,每個網格資源最多只能算繪 8 個 OmniLight 及 8 個 SpotLight。目前攝影機畫面中可算繪的 OmniLight 與 SpotLight 數量也分別上限為 256。這些限制目前無法調整。
使用相容性算繪器(Compatibility Renderer)時,每個網格資源最多只能算繪 8 個 OmniLight 及 8 個 SpotLight。此限制可以在【算繪 > 限制 > OpenGL】的進階專案設定中,調整 Max Renderable Elements 和/或 Max Lights per Object 來提升,但會犧牲效能並增加著色器編譯時間。反之,減少此限制可稍微提升效能並縮短著色器編譯時間。
對於所有算繪方法,一次最多可以看到 8 個方向光。但是,每個啟用陰影的附加 DirectionalLight 都會降低每個 DirectionalLight 的有效陰影解析度。這是因為定向陰影合集在所有燈光之間共用。
如果超出算繪限制,燈光將在攝影機移動期間開始突然進出,這可能會分散注意力。在輕節點上啟用 Distance Fade 可以幫助減少此問題,同時還可以提高效能。將網格體分割成更小的部分也有幫助,特別是對於關卡幾何(這也提高了剔除效率)。
如果你需要算繪的燈光數量超過該算繪器所允許的上限,可以考慮使用 baked lightmaps,並將燈光烘焙模式設為 靜態。這樣讓燈光完全烘焙,可大幅提升算繪效能。你也可以將自發光材質配合任何 全域照明 技術使用,來取代大面積照明的光源節點。
陰影貼圖
燈光可以可選地投射陰影. 這使它們具有更好的真實感(光線不會照到被遮擋的區域), 但它會帶來更大的性能開銷. 有一個通用陰影參數列表, 每個參數也有一個特定的功能:
Enabled(啟用):勾選以啟用此光源的陰影貼圖。
Opacity(不透明度):被遮蔽的區域會依這個不透明度係數變暗。預設陰影為全不透明,但可以調整讓某個光源產生半透明的陰影。
Bias(偏置):當此參數太小時,陰影會打在物體自己身上。當太大時,陰影會與物體本體分開。請調整到最適合你的狀態。
Normal Bias(法線偏置):當這個參數太低時會產生自遮蔽現象,太高則會讓陰影與物體本身出現偏移。請依實際需求微調。
Transmittance Bias(透光偏置):對於啟用透光的材質,這個參數太低會產生自遮蔽,太高則會讓陰影無法正確影響這些材質。請依需求微調。
Reverse Cull Face: 反轉表面剔除,當陰影貼圖使用反轉表面剔除算繪時,在某些場景表現更好。
模糊: 乘以此光源的陰影模糊半徑。這適用於傳統陰影貼圖以及接觸硬化陰影 (具有大於
0.0的 角距離 或 大小 的光源)。較高的值會導致更柔和的陰影,這也會顯得對於移動的物件在時間上更穩定。增加陰影模糊的缺點是它會使得用於過濾的顆粒狀圖案更明顯。另請參閱 陰影篩選模式。Caster Mask(投影遮罩):只有在這些圖層上的物件才會投射陰影。請注意,這個遮罩不會影響陰影投射到哪些物件上。
調整陰影偏移
下圖是調整偏置的樣子。預設值適用於大多數情況,但通常取決於幾何的大小和複雜程度。
如果對於特定光源的 陰影偏移 或 陰影法線偏移 設定太低,陰影將會「塗抹」到物體上。這會導致光源預期外觀變暗,且被稱為 陰影痤瘡:
另一方面,如果對於給定的光源,陰影偏移 或 陰影法線偏移 設定得太高,陰影可能看起來與物件分離。這稱為 彼得潘效應:
一般來說,增加**陰影法線偏差**優於增加**陰影偏差**。增加**陰影法線偏差**不會像增加**陰影偏差**那樣造成那麼多的麻煩,但它仍然可以有效解決大多數陰影痤瘡問題。增加**陰影法線偏差**的缺點是,它會使某些物體的陰影顯得更薄。
任何偏斜問題都可以透過 增加陰影貼圖解析度 來修正,代價是效能會降低。
備註
調整陰影貼圖設定是一門藝術 - 不存在「一刀切」的設定。為了獲得最佳視覺效果,您可能需要針對每個光源使用不同的陰影偏差值。
外觀變化注意事項:啟用光源陰影時,請注意該光源的外觀可能會與於相容性算繪器下未啟用陰影時有所不同。由於舊型行動裝置的限制,陰影採用多重算繪通道,因此帶有陰影的燈光會在 sRGB 色彩空間而非線性空間下算繪。這種算繪空間的變化有時會顯著改變燈光的表現。若想讓有陰影的光源看起來與無陰影時相近,可能需要調整該光源的能量(Energy)設定。
平行光
這是最常見的光線型別, 代表了很遠的光源(如太陽). 它也是計算中最便宜的光, 應該盡可能使用(雖然它不是計算起來最便宜的陰影貼圖, 但這點稍後再說).
平行光模擬覆蓋整個場景的無限數量的平行光線。平行光節點由指示光線方向的大箭頭表示。但是,節點的位置根本不會影響照明,它可以在任何地方。
每個被光線正面照射的表面都會被打亮,其他則保持黑暗。和平常大多數光源類型不同,平行光本質上非常單純,因此沒有特殊參數。
定向光也提供**角距離**屬性,它決定光的角度大小(以度為單位)。將其增加到「0.0」以上將使陰影在距離施法者更遠的地方變得更柔和,同時也會影響太陽在程式天空材質中的外觀。這稱為“接觸硬化”陰影(也稱為 PCSS)。
作為參考,從地球觀看太陽的角距離約為「0.5」。這種陰影很昂貴,因此如果在啟用陰影的燈光上將此值設為高於“0.0”,請檢查 PCSS 建議 中的建議。
方向光陰影貼圖
為了計算陰影貼圖, 會從正交視圖(僅深度)算繪整個場景(或直到最大距離). 但是, 這種方法存在問題, 因為靠近相機的物體會得到塊狀陰影.
為了解決這個問題,會使用一種稱為 PSSM(平行分割陰影貼圖,Parallel Split Shadow Maps) 的技術。它會將視椎體分割成 2 或 4 個區域,每個區域都擁有自己的陰影貼圖。如此一來,靠近玩家的小範圍區域能維持與遠方大區域相同解析度的陰影。當 DirectionalLight3D 開啟陰影時,預設即使用 4 分割的 PSSM。若某個物件體積大到同時出現在所有四個分割中,會導致繪製呼叫次數增加:該物件將總共被算繪五次(四次陰影貼圖分割、一次最終畫面算繪)。這會影響效能,了解這點有助於優化場景與預期效能表現。
有了它, 陰影變得更加詳細:
為了控制PSSM, 暴露了許多參數:
每個分割距離都是相對於相機最遠處(或陰影 Max Distance(最大距離) , 如果大於零)控制的, 因此 0.0 是眼睛位置, 1.0 是陰影在一定距離處結束的位置. 分割介於兩者之間. 預設值通常效果很好, 但調整第一個分割數值是很常見的, 可以為近處物件提供更多細節(比如第三人稱遊戲中的角色).
始終確保根據場景需要設定陰影**最大距離**。較小的最大距離將導致更好看的陰影和更好的性能,因為陰影算繪中需要包含的物件更少。您也可以調整**淡入淡出**來控制遠處陰影淡出的強度。對於**最大距離**在任何給定攝影機位置完全覆蓋場景的場景,您可以將**淡入淡出**增加到``1.0``以防止陰影在一定距離處褪色。在 最大距離 未完全覆蓋場景的場景中不應執行此操作,因為陰影會看起來在遠處突然被切斷。
有時, 一個分割與下一個之間的過渡看起來很糟糕. 要解決此問題, 可以打開 "Blend Splits"(混合分割) 選項, 犧牲細節以換取更平滑的過渡:
當物體垂直於光線時,"Normal Bias"(法線偏置) 參數可用於修復自陰影的特殊情況。唯一的缺點是它使陰影更薄。
最後,Pancake Size 是一個可以調整的屬性,可以在使用具有未細分網格的大型物件時修復遺失的陰影。僅當您發現與陰影偏移問題無關的陰影缺失時才更改此值。
全向光
全向光是一種點光源,可在所有方向上發射光,直至給定的半徑。
在現實生活中,光衰減是個和距離成反比的函式,這意味著全向光沒有半徑。這是一個問題,因為這意味著計算幾個全向光會變得很困難。
為了解決這個問題, 引入了 Range(範圍) 和衰減函式.
這兩個參數允許調整其在視覺上的工作方式, 以便找到美學上令人愉悅的結果.
OmniLight3D 中也提供 Size 參數。增加此值將使光線淡出速度變慢,遠離施法者時陰影會顯得更加模糊。這可以在一定程度上用於模擬區域光。這稱為“接觸硬化”陰影(也稱為 PCSS)。這種陰影很昂貴,因此如果在啟用陰影的燈光上將此值設為高於“0.0”,請檢查 PCSS 建議 中的建議。
全向光陰影貼圖
全向光的陰影貼圖相對簡單。需要考慮的主要問題是用於算繪它的演算法。
全向光陰影可以算繪為 "Dual Paraboloid"(雙抛物面)或"Cube Mapped"(方形對應) . 前者算繪速度很快但會導致變形, 而後者更正確但成本更高.
如果算繪的物件大部分是不規則的, 那麼Dual Paraboloid 通常就足夠了. 無論怎麼說, 由於這些陰影被快取在陰影合集中(後面會詳細講), 對於大多數場景而言, 它可能不會對性能產生影響.
啟用陰影的全向燈可以利用投影機。投影機紋理會將光的顏色乘以紋理上給定點的顏色。因此,一旦分配了投影機紋理,燈光通常會顯得更暗;您可以增加**能量**來彌補這一點。
全向光投影貼圖需要特殊的 360° 全景貼圖,類似於 PanoramaSkyMaterial 的貼圖。
使用下面的投影機紋理,獲得以下結果:
小訣竅
如果您以立方體貼圖影像的形式獲得了全向投影儀,則可以使用「這個基於網路的轉換工具<https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html>」__ 來轉換它們到單一全景圖像。
聚光
聚光與全向光類似,但是它們只發光到錐形(或“截斷”)中。它們可用於模擬手電筒、車燈、反射器、聚光燈等。這種型別的光也會向其指向的相反方向衰減。
聚光和 OmniLight(全向光)**共用 **Range(範圍)**和 **Attenuation(衰減),並新增了兩個額外參數:
Angle(角度) : 光線的光圈角度。
Angle Attenuation(角度衰減) : 錐形衰減, 有助於軟化錐形邊界.
聚光燈陰影貼圖
聚光燈具有與用於陰影貼圖的泛光燈相同的參數。與泛光燈相比,算繪點陰影貼圖要快得多,因為只需要算繪一個陰影紋理(而不是算繪 6 個面,或在雙拋物面模式下算繪 2 個面)。
啟用陰影的聚光燈可以利用投影機。投影機紋理會將光的顏色乘以紋理上給定點的顏色。因此,一旦分配了投影機紋理,燈光通常會顯得更暗;您可以增加**能量**來彌補這一點。
與全向光源投影機不同,聚光燈投影機貼圖不需要遵循特殊格式即可正確顯示。它將會以類似於 貼花 的方式映射。
使用下面的投影機紋理,獲得以下結果:
備註
廣角聚光燈的陰影品質比窄角度聚光燈低,因為陰影貼圖分佈在較大的表面上。當角度大於 89 度時,聚光燈陰影將完全停止工作。如果您需要更寬的燈光陰影,請使用泛光燈。
影子合集
與具有自己的陰影紋理的平行光不同,全向光和聚光被分配了陰影合集的槽位元。可以在“專案設定 -> 算繪 -> 品質 -> 陰影合集”中配置此合集。
這個解析度適用於整個陰影合集。該合集分為四個象限:
每個象限可以細分,分配任意數量的陰影貼圖。以下是預設細分方式:
陰影合集的空間分配方式如下:
分配邏輯很簡單. 最大的陰影貼圖大小(當不使用細分時)表示一個螢幕大小(或更大)的光. 細分區塊(較小的貼圖)表示遠離視圖並且成比例地較小的光的陰影.
分配邏輯很簡單. 最大的陰影貼圖大小(當不使用細分時)表示一個螢幕大小(或更大)的光. 細分區塊(較小的貼圖)表示遠離視圖並且成比例地較小的光的陰影.
每一幀,所有光源都會進行以下程序:
檢查燈光是否在正確大小的插槽上. 如果沒有, 重新算繪它並將其移動到更大/更小的插槽.
檢查影響陰影貼圖的任何物件是否已更改. 如果是的話, 重新算繪光線.
如果上述情況均未發生, 則不執行任何操作, 陰影保持不變.
如果某個象限的槽滿了,燈光會根據其大小和距離被分配到更小的槽。如果所有象限的槽都滿了,就算有開陰影,部分燈光也無法算繪陰影。
預設陰影分配策略允許在相機視錐體中啟用陰影的情況下算繪最多 88 個燈光 (4 + 4 + 16 + 64):
第一個也是最詳細的象限可以儲存 4 個陰影。
第二象限可以儲存另外4個陰影。
第三象限可以儲存16個陰影,細節較少。
第四個也是最不詳細的象限可以儲存 64 個陰影,細節更少。
每個象限使用更多數量的陰影可以在啟用陰影的情況下支援更多數量的總燈光,同時還可以提高效能(因為每個燈光的陰影將以較低的解析度算繪)。然而,增加每個象限的陰影數量是以降低陰影品質為代價的。
此分配策略適用於大多數遊戲, 但在某些情況下你可能會想用一個單獨分開的貼圖(例如, 一個自上向下看的遊戲, 其中所有燈光大小大概相同, 所有象限的細分可能會具有相同大小).
平衡性能與品質
陰影算繪是 3D 算繪性能方面的重要議題。做出正確的選擇非常重要,這樣才能避免製造出瓶頸。
平行光的陰影品質設定可以在執行時透過 RenderingServer 的相關方法調整。
位置(全向/聚光)陰影品質設定可於執行時在根 Viewport 上更改。
陰影貼圖大小
高陰影解析度會產生更清晰的陰影,但會帶來顯著的效能成本。還應該注意的是,更清晰的陰影並不總是更真實。在大多數情況下,這應該保持在預設值“4096”,或者對於低端 GPU 減少到“2048”。
如果位置陰影在減少陰影貼圖大小後變得太模糊,您可以透過調整 陰影圖集 象限以包含較少的陰影來抵消這個問題。這將允許每個陰影以更高的解析度算繪。
陰影篩選模式
可以在此處選擇多個陰影貼圖品質設定。對於具有詳細紋理的場景,預設的 Soft Low 可以在效能和品質之間取得良好的平衡,因為紋理細節將有助於使抖動圖案不那麼明顯。
但在紋理細節較少的專案中,陰影抖動圖案會變得明顯。你可以啟用 時間抗鋸齒(TAA)、AMD FidelityFX Super Resolution 2.2 (FSR2)、快速近似抗鋸齒(FXAA),或者將陰影濾鏡品質提升至 Soft Medium 或更高,以減少這個現象。
軟非常低**設定將自動減少陰影模糊,從而使低樣本數造成的偽影不那麼明顯。相反,**Soft High 和 Soft Ultra 設定將自動增加陰影模糊,以更好地利用增加的樣本數。
16 位與 32 位
預設情況下,Godot 使用 16 位元深度紋理進行陰影貼圖算繪。在大多數情況下建議這樣做,因為它的性能更好,而且品質沒有明顯差異。
如果停用 16 位元,則將使用 32 位元深度紋理。這可以減少大場景和啟用陰影的大燈光中的偽影。然而,差異通常幾乎不可見,但這可能會產生顯著的效能成本。
燈光/陰影的距離淡出
OmniLight3D 和 SpotLight3D 提供了一些能夠隱藏遠距離燈光的屬性。如果是在大型場景中,並且存在幾十盞燈,就能夠顯著提升性能。
啟用: 控制距離漸隱 (一種 細節層次 形式) 是否啟用。光線將會在 起始 + 長度 期間漸隱,之後它將會被剔除並且完全不會被發送到著色器。使用此功能以減少一個場景中活動光線的數量,進而提升效能。
開始: 光線開始消失時距相機的距離(以 3D 單位表示)。
陰影: 陰影開始消失時距相機的距離(以 3D 單位表示)。與光線相比,這可用於更快地淡出陰影,從而進一步提高性能。僅當為燈光啟用陰影時才可用。
長度: 光線和陰影淡出的距離(以 3D 單位表示)。光線在這段距離內慢慢變得更透明,最後完全不可見。數值越高,淡出過渡越平滑,這在相機快速移動時更適合。
PCSS 建議
百分比接近軟陰影 (PCSS) 提供更真實的陰影貼圖外觀,半影大小會根據施法者與接收陰影的表面之間的距離而變化。這會帶來很高的性能成本,特別是對於定向燈而言。
為了避免性能問題,建議:
在給定時間僅使用少量啟用了 PCSS 陰影的燈光。這種效果通常在大而明亮的燈光下最為明顯。較微弱的輔助光源通常不會從使用 PCSS 陰影中受益匪淺。
為使用者提供禁用 PCSS 陰影的設定。在定向光源上,這可以透過在腳本中將 DirectionalLight3D 的「light_angle_distance」屬性設為「0.0」來完成。對於位置光源,這可以透過在腳本中將 OmniLight3D 或 SpotLight3D 的「light_size」屬性設為「0.0」來完成。
專案工作流程
投影器的算繪方式也會影響效能。在 算繪 > 紋理 > 光投影器 > 濾鏡 的進階專案設定中,你可以設定投影紋理的過濾方式。 Nearest/Linear 不使用 mipmap,算繪速度較快,但投影在遠處看會有顆粒感。 Nearest/Linear Mipmaps 在遠處較平滑,但從斜角觀看時會模糊。這時可用 Nearest/Linear Mipmaps Anisotropic (各向異性),這是最高品質,但計算最昂貴的模式。
如果您的專案具有像素藝術風格,請考慮將濾鏡設定為**最近**值之一,以便投影機使用最近鄰篩選。否則,請堅持**線性**。