☰
Godot DirectionalLight2D 完全指南:平行光、日光月光模拟与 2D 阴影裁剪
2026/10/5 2:11:03 网站建设 项目流程
  • 文档
  • 教程
  • 游戏开发

【免费下载链接】godot-docs

Godot Engine official documentation

项目地址:https://gitcode.com/GitHub_Trending/go/godot-docs
点击查看免费下载

DirectionalLight2D 是 Godot 中模拟太阳光、月光的核心 2D 光照节点:它以覆盖全场景的无限平行光线为特征,光源位置不影响光照结果,只有旋转角度决定光线的方向。本文将以 Godot 官方文档(classes/class_directionallight2d.rst)为骨架,结合 2D 光照与阴影教程、Light2D 基类文档 及 CanvasItem 着色器参考,系统讲解该节点的光照方向语义、height 与 max_distance 两个专属属性、继承自 Light2D 的通用光照/阴影参数,以及在实际 2D 场景(横版平台游戏、俯视角游戏)中的完整配置流程。读完你将能够独立搭建一套带法线贴图与软阴影的 2D 日光照明系统,并理解其底层渲染原理。

DirectionalLight2D 是什么

DirectionalLight2D 是一种 Light2D 节点,它模拟的是来自无穷远处的无限平行光线,覆盖整个 2D 场景。这类光适用于强度高、距离场景极远的照明源——最典型的用途就是模拟太阳光或月光。

其完整继承链为:

DirectionalLight2D → Light2D → Node2D → CanvasItem → Node → Object

与同属 Light2D 子类的 PointLight2D(点光源/位置光)不同,方向光的特征在于:

  • 光线彼此平行,如同太阳或月亮距离受光面无穷远;
  • 节点位置被忽略,只有旋转(basis)决定光线方向;
  • 因此在场景中移动 DirectionalLight2D 节点不会改变光照效果,旋转它才会。

光照方向语义:+Y 轴与全局基

官方文档明确规定了方向光的发射语义:

光线沿节点全局基(global basis)的+Y 方向发射。对于未旋转的光源,这意味着光线向下发射。节点的位置被忽略,只有基用于确定光的方向。

这是 2D 光照方向与 3D 的一个关键差异。在 Godot 2D 坐标系中,Y 轴向下为正,因此:

  • 默认(不旋转)的 DirectionalLight2D 发出向下的光,适合"天光从画面顶部照向地面"的常规场景;
  • 通过rotation_degrees或rotation调整节点角度,即可让光线从任意斜向照射——例如清晨(低角度斜光)或傍晚(另一侧斜光),只需要旋转 DirectionalLight2D 节点即可,无需移动它。

从底层实现看,RenderingServer 中通过枚举CANVAS_LIGHT_MODE_DIRECTIONAL = 1标记 2D 方向光(sun/moon light),并在 CanvasItem 着色器中通过内置变量区分方向光与点光:LIGHT_POSITION对 DirectionalLight2D 恒为(0.0, 0.0, 0.0),而LIGHT_IS_DIRECTIONAL为true(详见 canvas_item_shader.rst)。这意味着在自定义 2D 着色器里,可以依据LIGHT_IS_DIRECTIONAL分支编写专属于方向光的着色逻辑。

专属属性详解

DirectionalLight2D 在 Light2D 基类之上只新增了两个专属属性:

height(高度,默认0.0)

用于2D 法线贴图(normal mapping)的光源虚拟高度,取值范围从0(与受光面平行)到1(与受光面垂直)。默认值0.0表示光线与表面完全平行,此时若使用法线贴图,光照几乎不可见——因此官方建议在启用法线贴图后适当增大 height(例如 0.5~1.0 之间的数值),并在启用法线贴图后略微提升 Energy 以补偿观感上的变暗。

需要特别强调的是:height 只影响法线贴图表面的视觉表现,不影响阴影的外观(详见 2D 光照教程)。这与法线贴图的工作原理一致——法线贴图以逐像素方式记录表面朝向,光源高度决定入射角,从而改变光照强度分布。

对应的 setter/getter 为set_height(value)/get_height(),该对方法实际继承自 Light2D 基类(见 class_light2d.rst),在 PointLight2D 与 DirectionalLight2D 上共用。

max_distance(最大距离,默认10000.0)

物体与摄像机中心的距离超过该值(以像素计)时,其阴影会被裁剪(cull)。减小此值可以防止摄像机视野之外的物体投射阴影,同时提升渲染性能。

需要注意Camera2D.zoom不会被max_distance考虑在内,这意味着缩放(zoom)越大,阴影会显得越早淡出。理解这一点对制作镜头缩放的横版游戏尤为重要:如果场景中的物体在远摄视角下阴影异常消失,优先检查 max_distance 与当前 Camera2D 的 zoom 组合。

在实战中,max_distance 是方向光性能调优的核心旋钮之一:方向光阴影作用于整幅场景,若不裁剪远处物体的阴影,渲染负担会显著增加。配合将场景边界外的 LightOccluder2D 排除在外,可获得明显的性能收益。

继承自 Light2D 的通用属性

DirectionalLight2D 与 PointLight2D 共享 Light2D 基类提供的光照与阴影参数(完整列表见 Light2D 属性表),在 Inspector 中表现为以下项目:

属性默认值说明
Enabledtrue是否发光。与隐藏节点不同,禁用此属性不会隐藏光的子节点
Editor Onlyfalse仅在编辑器内可见,运行时自动禁用,便于编辑辅助
ColorColor(1, 1, 1, 1)光颜色,可做日出/日落的暖色、月光冷色等艺术化处理
Energy1.0强度倍率,越大越亮
Blend Mode0(Add)混合模式:BLEND_MODE_ADD=0加法(默认,最常用)、BLEND_MODE_SUB=1减法(负光,用于特效)、BLEND_MODE_MIX=2线性插值混合
Range > Z Min / Z Max-1024/1024受光物体的 z 索引范围
Range > Layer Min / Max0/0受光物体的视觉层范围
Range > Item Cull Mask1控制哪些节点接收光照(依据对方 CanvasItem 的 light_mask)
Shadow > Enabledfalse是否投射阴影
Shadow > ColorColor(0,0,0,0)阴影颜色,alpha 控制阴影着色程度,默认纯黑
Shadow > Filter0(None)阴影过滤:SHADOW_FILTER_NONE=0(硬边,最快)、SHADOW_FILTER_PCF5=1(5 采样 PCF)、SHADOW_FILTER_PCF13=2(13 采样,最软但最慢)
Shadow > Filter Smooth0.0仅在 Filter 为 PCF5/PCF13 时生效,值越高阴影越软,但可能产生可见的带状伪影
Shadow > Item Cull Mask1控制哪些 LightOccluder2D投射阴影

关键差异:光照剔除掩码(light cull mask)对 DirectionalLight2D 无效,但阴影剔除掩码(shadow cull mask)有效。

DirectionalLight2D 会无条件照亮所有 2D 节点,无论对方的 CanvasItem.light_mask 设置为何值。因此:

  • 想用"某些物体不被方向光照亮"的方式做分层/混合,是行不通的;
  • 想让某些遮挡物不投射方向光阴影,则可以在方向光的Shadow > Item Cull Mask与遮挡物的Occluder Light Mask上做位掩码匹配(详见 class_light2d.rst 的 Note 说明)。

这一行为也体现在 Inspector 中:方向光的 Range > Item Cull Mask 在运行时会被忽略。

实战:搭建一套日光/月光照明

以下是官方教程推荐的完整 2D 照明节点组合(2D 光照与阴影教程):

  1. CanvasModulate—— 设置场景基础"环境色",代表没有任何 2D 光照射区域最终的照明颜色。没有它,2D 光只会叠加在原本"全亮"的画面之上,最终场景过亮。
  2. DirectionalLight2D—— 太阳光或月光。
  3. PointLight2D—— 火炬、篝火、弹丸等局部光源(可选用)。
  4. LightOccluder2D—— 定义阴影投射体,可独立放置,也可作为 TileMapLayer 的一部分。
  5. 接收光照的普通 2D 节点(Sprite2D、TileMapLayer 等)。

创建方向光并开启阴影的步骤:

  1. 在场景中新建DirectionalLight2D节点;
  2. 调整rotation(如 45°)获得斜向日光,或保持 0° 获得垂直向下光;
  3. 在 Inspector 中设置Shadow > Enabled为true;
  4. 为需要投射阴影的 Sprite2D 创建LightOccluder2D:选中 Sprite2D,点击 2D 编辑器顶部的Sprite2D菜单,选择Create LightOccluder2D Sibling自动生成;若轮廓不贴合,可调整对话框中的Grow (pixels)/Shrink (pixels)后点击Update Preview反复校正(详见 阴影设置章节)。也可以手动新建 LightOccluder2D,用 2D 编辑器顶部的 "+" 按钮绘制遮挡多边形。

启用阴影后若没有视觉差异,原因几乎总是:场景中还没有任何遮挡体(occluder)。阴影必须以 LightOccluder2D 的遮挡多边形为投射基础。

注意:背景颜色不接收任何光照。若想让光照作用于背景,需要为背景添加可视表示(如 Sprite2D),并使用其Region属性配合Texture > Repeat = Enabled制作平铺背景。

阴影外观调优

  • 硬阴影:Shadow > Filter 保持None,渲染最快,适合像素风("块状"视觉);
  • 软阴影:设为PCF5可获得柔和阴影;PCF13更软但渲染开销最高,官方建议全场景同时使用的数量要克制;
  • Filter Smooth:控制 PCF5/PCF13 下的软化程度,过高会出现带状条纹伪影(尤其 PCF5);
  • Shadow > Color的 alpha 通道控制阴影着色强度,可做艺术化调整。

已知限制:方向光阴影永远表现为无限长,无论 height 属性如何设置——这是 Godot 2D 光照阴影渲染方法本身的局限(教程原文)。若需要"有限长"的方向光阴影,官方给出的方案是:关闭 DirectionalLight2D 的阴影,改用自定义着色器读取由场景中 LightOccluder2D 自动生成的2D 有向距离场(signed distance field, SDF)。

像素风游戏的阴影像素化

Godot 在视口像素分辨率上计算 2D 光照与阴影,而非源纹理的 texel 分辨率,因此最近邻纹理过滤并不会让光照/阴影变成像素风。要实现与像素美术风格匹配的块状光照阴影,需在 CanvasItem 着色器中把LIGHT_VERTEX与SHADOW_VERTEX对齐到像素网格(示例见 2D 光照教程):

shader_type canvas_item; uniform float pixel_size = 4.0; void fragment() { // 将光照与阴影对齐到像素网格。 LIGHT_VERTEX.xy = floor(LIGHT_VERTEX.xy / pixel_size) * pixel_size; SHADOW_VERTEX = floor(SHADOW_VERTEX / pixel_size) * pixel_size; // 正常渲染。 COLOR = texture(TEXTURE, UV); }

其原理是先用pixel_size除以坐标转换到网格空间,再用floor()向下取整到最近网格点,最后乘回以还原到屏幕空间,从而强制引擎从离散网格位置采样光照。

法线贴图与 specular 贴图下的方向光

DirectionalLight2D 与 PointLight2D 均支持法线贴图与高光(specular)贴图,二者可赋予任意继承 Node2D 或 Control 的 2D 元素。配置方式是在 Sprite2D 等节点的纹理属性上创建CanvasTexture资源,然后分别指定:

  • Diffuse > Texture:基础颜色纹理;
  • Normal Map > Texture:法线贴图(从高度图生成,可用 Laigter 等工具辅助制作);
  • Specular > Texture:高光贴图,控制每个像素的反射强度,通常为灰度图;
  • Specular > Color:高光反射的颜色倍率;
  • Specular > Shininess:高光指数,值越低反射越亮越弥散,越高越集中(适合潮湿表面)。

启用法线贴图后,方向光看起来会明显变弱——此时应提高 DirectionalLight2D 的 Height 属性(默认 0.0 与表面平行,几乎不出效果),并可小幅提升Energy来接近启用法线贴图前的观感(官方说明)。

性能与工程建议

  • max_distance 是最重要的方向光性能开关:场景较大时,将其从默认的10000.0调低到与摄像机视野匹配的数值,可裁剪视野外物体的阴影投射;
  • 方向光阴影在整幅视口内计算,若画面中有大量遮挡物,优先使用Shadow > Item Cull Mask与遮挡物 Occluder Light Mask 的位掩码组合,将不必要的投射体排除;
  • 对于短生命周期动态特效(子弹、爆炸),可以用加法混合的 Sprite2D替代真正的 2D 光以换取性能(无需进入单独渲染管线,也支持 AnimatedSprite2D 动画化);但要注意其混合公式不够精确、不能投射阴影、忽略法线贴图与高光贴图这三项代价(官方对比);
  • 在自定义着色器中区分方向光:LIGHT_IS_DIRECTIONAL为true且LIGHT_POSITION恒为(0,0,0),据此可编写全局方向光专用的光照响应逻辑。

参考资源

  • DirectionalLight2D 类文档(本文主体)
  • 2D 光照与阴影完整教程(含点光、阴影设置、法线贴图、像素化技巧)
  • Light2D 基类文档(共享属性、BlendMode 与 ShadowFilter 枚举)
  • CanvasItem 类文档(light_mask、z_index 等接收光照相关属性)
  • CanvasItem 着色器参考(LIGHT_IS_DIRECTIONAL、LIGHT_POSITION 等内置光照变量)
  • RenderingServer 文档(CANVAS_LIGHT_MODE_DIRECTIONAL 底层枚举)
  • 文档
  • 教程
  • 游戏开发

【免费下载链接】godot-docs

Godot Engine official documentation

项目地址:https://gitcode.com/GitHub_Trending/go/godot-docs
点击查看免费下载

相关推荐

上一篇:Humanizer 的 IDateOnlyHumanizeStrategy 接口:定制 DateOnly.Humanize 相对日期策略的完整指南
下一篇:5分钟打造你的专属Obsidian知识管理中心:从空白到高效工作流的终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询