Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

2D 燈光和陰影

前言

預設情況下,Godot 中的 2D 場景採用無光照著色,看不到燈光和陰影。雖然渲染速度很快,但無陰影的場景看起來會很平淡。Godot 提供了可以使用即時 2D 照明和陰影的功能,可以大大增強專案的層次感。

無 2D 燈光或陰影,場景採用無光照著色

無 2D 燈光或陰影,場景採用無光照著色

:ref:`doc_2d_lights_and_shadows`

2D 燈光和陰影

:ref:`doc_2d_lights_and_shadows`

2D 燈光和陰影

節點

完整的二維照明設定涉及多個節點:

  • CanvasModulate 用於使場景變暗

  • :ref:`PointLight2D <class_PointLight2D>`(用於全向或點光源)

  • :ref:`DirectionalLight2D <class_DirectionalLight2D>`(用於日光或月光)

  • LightOccluder2D

  • 其他可接收光照的 2D 節點,如 Sprite2D 或 TileMap。

CanvasModulate 用於指定一種顏色作為“環境”基色,從而使場景變暗。這是任何 2D 燈光都 無法 到達區域的最終照明顏色。如果沒有 CanvasModulate 節點,由於 2D 燈光只會照亮現有的無陰影外觀(看起來完全亮了),最終場景看起來會過於明亮。

Sprites 用於顯示燈泡、背景和產生陰影的物體的紋理。

Light2Ds 用於點亮場景. 光通常的工作方式是在場景的其餘部分新增選定的紋理以模擬光照. 但它可以以其他方式使用, 例如遮罩部分場景.

LightOccluder2Ds 用於告訴著色器, 場景的哪些部分投射陰影. 陰影僅出現在 Light2D 所覆蓋的區域, 它們的方向基於 Light 的中心.

LightOccluder2Ds 用於告訴著色器, 場景的哪些部分投射陰影. 陰影僅出現在 Light2D 所覆蓋的區域, 它們的方向基於 Light 的中心.

備註

背景色 不會 接收任何光照。如果要在背景上投射燈光,則需要為背景新增視覺化表示,例如 Sprite2D。

Sprite2D 的 Region 屬性有助於快速建立重複的背景紋理,但要記住在 Sprite2D 屬性中將 Texture > Repeat 設定為 Enabled

骨骼權重

點光源(也稱位置光源)是 2D 照明中最常見的元素。點光源可用於表示火把、火、射彈等發出的光。

PointLight2D 提供了以下屬性,可在屬性面板中進行調整:

  • 紋理: 用作光源的紋理。紋理的大小決定光源的大小。紋理可以有一個 alpha 通道,這在使用 Light2D 的 Mix 混合模式時非常有用,但在使用 Add (預設)或 Subtract 混合模式時則不需要。

  • 偏移量: 燈光紋理的偏移量。與移動燈光節點不同,改變偏移量 不會 導致陰影移動。

  • 紋理縮放: 燈光大小的乘法器。數值越大,燈光越亮。較大的燈光會影響螢幕上更多的像素,因此在增大燈光尺寸前要考慮到這一點。

  • 高度: 燈光在法線貼圖中的虛擬高度。預設情況下,燈光與接收燈光的表面非常接近。如果使用法線貼圖,這將使燈光幾乎不可見,因此可以考慮增加此值。只有在使用法線貼圖的表面上,調整燈光的高度才會產生明顯的不同。

如果沒有預製紋理可用於燈光,可以使用這種 “中性 ”點光源紋理(按右鍵 > 圖像另存為... ):

匯入紋理

匯入紋理

如果您需要不同的漸變,可以通過在燈光的**紋理**屬性上分配 新建 GradientTexture2D 來程式化地建立紋理。建立資源後,展開其 Fill 部分並將填充模式設定為 Radial 。然後,您需要調整漸變本身,使其從不透明的白色開始到透明的白色,並將其起始位置移動到中心。

平行光

Godot 4.0 的新功能是在 2D 中實作定向照明。定向照明用於表現陽光或月光。光線相互平行投射,就好像太陽或月亮離受光表面無限遠一樣。

DirectionalLight2D 提供以下的屬性:

  • 高度: 燈光在法線貼圖中的虛擬高度( 0.0 = 平行於曲面, 1.0 = 垂直於曲面)。預設情況下,燈光與接收燈光的表面完全平行。如果使用法線貼圖,這將使燈光幾乎不可見,因此可以考慮增大此值。調整燈光的高度只會對使用法線貼圖的表面產生視覺差異。 高度 不會影響陰影的外觀。

  • 最大距離: 物體距離相機中心的最大距離(單位:像素)。減小該值可以防止對位於相機外的物體投射陰影(同時還能提高性能)。 最大距離 不考慮 Camera2D 的縮放,這意味著在較高的縮放值下,當縮放至給定點時,陰影會更快消失。

備註

無論 Height 屬性的值是多少,定向陰影看起來總是無限長。這是 Godot 中用於 2D 燈光的陰影渲染方法的限制。

不想獲得無限長的定向陰影,應禁用 DirectionalLight2D 中的陰影,並使用自訂著色器來讀取 2D 帶符號距離場。該距離場從場景中的 LightOccluder2D 節點自動生成。

建立屬性群組

PointLight2D 和 DirectionalLight2D 都提供共同的屬性,這些屬性是 Light2D 基底類別的一部分:

  • 啟用: 允許切換燈光的可見性。與隱藏燈光節點不同,禁用此屬性不會隱藏燈光的子節點。

  • 僅編輯器: 如果啟用,燈光僅在編輯器中可見。在運作的專案中將自動禁用。

  • 顏色: 燈光的顏色。

  • 能量: 燈光強度乘數。數值越大,光線越亮。

  • 混合模式: 用於光線計算的混合公式。預設的 新增(Add) 適合大多數使用情況。 減(Subtract) 可用於負光,負光在物理上並不精確,但可用於特殊效果。 混合(Mix) 模式通過線性插值將燈光紋理對應的像素值與燈光下方的像素值混合。

  • 範圍 > Z 下限: 受光線影響的最小 Z 值。

  • 範圍 > Z 上限: 受光線影響的最大 Z 值。

  • 範圍 > 層下限: 受光線影響的最小層數值。

  • 範圍 > 層上限: 受光線影響的最大層數值。

  • 範圍 > 對象遮罩: 根據其他節點的可視層選項**Occluder Light Mask**(遮擋掩膜),控制那些節點接收到來自這個節點的光線。通過這種方式可以讓某些物體不被光線照射。

設定 SCons

啟用一個 PointLight2D 或者 DirectionalLight2D 節點的 Shadow > Enabled 屬性之後,你將看不到任何變化。這是因為在你的場景中還沒有任何節點擁有投射陰影需要使用的 遮擋器

要在場景中顯示陰影,必須在場景中新增 LightOccluder2D 節點。這些節點還必須具有與精靈輪廓相配對的遮光多邊形。

除了多邊形資源(必須設定多邊形資源才能產生視覺效果)之外,LightOccluder2D 節點還有兩個屬性:

  • **SDF碰撞:**如果啟用,則遮擋器將成為可在自訂著色器中使用的即時生成的 簽章距離欄位 (signed distance field)的一部分。當不使用從此 SDF 中讀取的自訂著色器時,啟用這個功能不會帶來視覺上的差異,並且沒有性能成本,因此預設情況下為方便起見它是啟用的。

  • 遮擋器光照遮罩: 這是與 PointLight2D 和 DirectionalLight2D 的 Shadow > Item Cull Mask 屬性一起使用的功能,以控制哪些物件為每個光照投射陰影。這可用於防止特定物件投射陰影。

Godot 沒有使用限制

自動生成光遮蔽器

遮擋器可以自動地 Sprite2D 節點上建立,需要選中節點,按一下2D編輯器頂部的 Sprite2D**功能表,然後選擇 **建立 LightOccluder2D 兄弟節點\\從而自動進行。

在出現的視窗中,一個外框將會包裹在你的精靈的邊緣。如果外框貼合在了你的精靈的邊緣上,你可以點擊**確定**。如果外框離你的精靈邊緣太遠(或者它穿過了你的精靈的邊緣),調整**擴充(像素)**和**收縮(像素)**,然後點擊**更新預覽**。重複這一個操作直到你對結果滿意為止。

手動繪製光遮蔽器

建立一個 LightOccluder2D 節點,然後選中節點,點擊 2D 編輯器頂部的 “+” 按鈕。在詢問是否要新增一個多邊形資源的時候選擇**建立**。然後你就可以通過點擊新增頂點的方式繪製遮光多邊形了。你可以通過右鍵已經建立的頂點來刪除它們,並且你可以點擊並拖動一個已經存在的線段上來新增新的頂點。

啟用陰影的 2D 燈光能夠調整以下屬性:

  • **Color:**陰影區域的顏色。預設情況下,陰影區域是全黑的,但這可以出於藝術目的而改變。顏色的 alpha 通道控制的是陰影被指定顏色著色的程度。

  • Filter:**陰影所使用的篩選模式。預設值為 **None,渲染速度最快,並且非常適合像素藝術風格的遊戲(因為它具有“方塊”視覺效果)。如果你想要柔和的陰影,請使用 PCF5PCF13 則更柔和,但渲染需求更高。由於渲染成本較高,PCF13 只應用於少量光源同時存在的情況下。

  • Filter Smooth:**篩選平滑。控制的是當 **FilterPCF5 或* PCF13* 時,應用於陰影的柔化程度。較高的值會導致陰影更加柔和,但可能會出現帶狀偽影(特別是使用 PCF5 時)。

  • **Item Cull Mask:**專案剔除遮罩。控制的是哪些 LightOccluder2D 節點能夠投射陰影,取決於對應的 **Occluder Light Mask**(遮擋器燈光遮罩)屬性。

硬或軟陰影。

硬或軟陰影。

柔和陰影(PCF13,濾鏡平滑度 1.5)

柔和陰影(PCF13,濾鏡平滑度 1.5)

由於濾波平滑度太高(PCF5,濾波平滑度 4),陰影變得柔和,並出現條紋偽影

由於濾波平滑度太高(PCF5,濾波平滑度 4),陰影變得柔和,並出現條紋偽影

遮擋模式

**LightOccluder2D 遵循常規的 2D 繪圖順序。**這對於 2D 燈光而言非常重要,因為可以用來控制遮擋器是否應該遮擋精靈本身。

如果 LightOccluder2D 節點是精靈的*兄弟*節點,並且場景樹中的遮擋器被放在精靈的*下方*,會遮擋住精靈本身。

如果 LightOccluder2D 節點是一個精靈的子節點,如果在 LightOccluder2D 節點中禁用了 **Show Behind Parent**(顯示在父級之後)這個遮擋器將遮擋住精靈本身(該選項預設禁用)。

法線和鏡面貼圖

法線貼圖和鏡面貼圖可以大大提升你的2D光照的立體感。與3D渲染類似,法線貼圖可以根據接收光線的表面方向來改變光線的強度,從而使照明效果不再平面化(按像素進行調整)。鏡面貼圖通過讓一部分光線反射回觀察者來進一步改善視覺效果。

PointLight2D 和 DirectionalLight2D 都支援法線貼圖和鏡面貼圖。自 Godot 4.0 起,法線貼圖和鏡面貼圖可分配給任何 2D 元素,包括繼承自 Node2D 或 Control 的節點。

法線貼圖表示每個像素 “指向” 的方向。引擎會利用這些資訊,以物理上合理的方式將光照正確應用到 2D 表面。法線貼圖通常由手繪的高度貼圖建立,但也可以由其他紋理自動生成。

鏡面貼圖定義了每個像素對光線的反射程度(如果鏡面貼圖包含顏色,則定義反射的顏色)。亮度值越高,紋理上指定位置的反射就越亮。鏡面貼圖通常以漫反射紋理為基礎,通過手動編輯建立。

小訣竅

如果在你的精靈中沒有使用法線貼圖或者鏡面貼圖,可以使用免費的開源工具`Laigter <https://azagaya.itch.io/laigter>`來生成。

要在 2D 節點上設定法線貼圖和/或鏡面貼圖,請為繪製節點紋理的屬性建立一個新的 CanvasTexture 資源。例如,在一個 Sprite2D 節點上建立一個新的 CanvasTexture 資源:

為 Sprite2D 節點建立 CanvasTexture 資源

為 Sprite2D 節點建立 CanvasTexture 資源

展開新建立的資源。您可以找到需要調整的幾個屬性:

  • **Diffuse > Texture:**(漫反射 > 紋理)基礎的顏色貼圖。在這個屬性中,載入你將使用在精靈本身的紋理。

  • **Normal Map > Texture:**(法線貼圖 > 紋理)法線貼圖的紋理。在這個屬性中,你可以載入從高度圖生成的法線貼圖紋理(見上面的提示)。

  • **Specular > Texture:**(鏡面反射 > 紋理)鏡面貼圖紋理,可以控制漫反射紋理上每個像素的鏡面反射強度。鏡面貼圖通常使用灰度反射,但是它也可以包含色彩來增強反射的顏色。在這個屬性中,載入一個已建立的鏡面貼圖紋理(見上面的提示)。

  • **Specular > Color:**(鏡面反射 > 顏色)鏡面反射的顏色乘數。

  • **Specular > Shininess:**(鏡面反射 > 光澤度)用於鏡面反射的高光指數。值越低,反射的明亮度和擴散性會增加,而值越高,反射會更加局部化。較高的值適用於濕潤表面。

  • **Texture > Filter:**(紋理 > 篩檢程式)可以設定為覆蓋紋理篩選模式,無論節點屬性設定如何(或**渲染 > 紋理 > 畫布紋理 > 預設紋理篩選**專案設定)。

  • **Texture > Repeat:**(紋理 > 重複)可以設定為覆蓋紋理篩選模式,無論節點的屬性如何設定(或者**渲染 > 紋理 > 畫布紋理 > 預設紋理重複**專案設定)。

啟用法線貼圖後,你可能會注意到燈光會顯得較弱。為了解決這個問題,可以增加 PointLight2D 和 DirectionalLight2D 節點上的 Height 屬性。也可以略微增加燈光的 Energy 屬性,以接近啟用法線貼圖之前的照明強度。

使用新增式精靈作為 2D 燈光的快速替代品

如果在使用 2D 燈光時遇到性能問題,不妨將其中一些節點替換為使用疊加混合的 Sprite2D 節點。這尤其適用於短暫的動態效果,如子彈或爆炸。

新增式精靈的渲染速度要快得多,因為它們不需要通過單獨的渲染管道。此外,這種方法還可以與 AnimatedSprite2D(或 Sprite2D + AnimationPlayer)一起使用,這樣就可以建立動畫二維 “燈光”。

不過,與 2D 燈光相比,新增式精靈有一些缺點:

  • 與 “實際 ”二維光照相比,混合公式並不準確。這在光線充足的區域通常不是問題,但這會妨礙新增精靈去正確照亮那些完全黑暗的區域。

  • 新增式精靈不能投射陰影,因為它們不是燈光。

  • 新增式精靈會忽略其他精靈上使用的法線貼圖和鏡面貼圖。

要顯示一個混合疊加效果的精靈,需要建立一個 Sprite2D 節點並分配一個紋理給它。在檢視視窗中,往下滾動到 CanvasItem > Material 部分,展開它並點擊 Material 屬性旁邊的下拉式功能表。選擇 New CanvasItemMaterial,點擊新建的材質來編輯它,然後將 Blend Mode 設定為 Add