2D 灯光和阴影

前言

灯与影 演示项目解释了2D灯光的工作原理. 本节首先简要介绍了最终demo所使用的资源, 然后介绍了如何逐步实现类似demo的场景. 官方演示存储库 中找到. 我建议您在开始之前下载它. 或者, 也可以在项目管理器中下载. 在启动Godot时在顶部栏中选择 “模板(Templates)” 选项卡并搜索 “2D Lights and Shadows Demo”.

场景布置

对于这个演示, 我们使用四种纹理: 两种用于灯光, 一种用于那些会产生阴影的物品, 一种用于背景. 如果想单独下载它们, 我在这里列出了所有链接. bg.png ). 你不一定需要背景, 但我们还是在演示中用了一个. caster.png ) . 对跳跃游戏, 它可能是墙或任何其他投射阴影的物体. light.png ) . 如果单击该链接, 您会注意到它有多大. 用于灯光的图像应覆盖您希望灯光覆盖的区域. 此图像为1024x1024像素, 因此您应该使用它来覆盖游戏中的1024x1024像素. spot.png ) . 该演示使用灯泡来显示灯光的位置, 使用较大的灯光图片来显示灯光对场景其余部分的影响.

节点

该演示使用了四个不同类型的节点:

  • CanvasModulate
  • Sprite
  • Light2D
  • LightOccluder2D CanvasModulate 用于使场景变暗. Sprites 用于显示灯泡, 背景和产生阴影的物体的纹理. Light2Ds 用于点亮场景. 光通常的工作方式是在场景的其余部分添加选定的纹理以模拟光照. 但它可以以其他方式使用, 例如屏蔽部分场景. LightOccluder2Ds 用于告诉着色器, 场景的哪些部分投射阴影. 阴影仅出现在 Light2D 所覆盖的区域, 它们的方向基于 Light 的中心.

    灯光

    Lights 覆盖各自纹理的整个范围. 它们使用Additive Blending将其纹理颜色添加到场景中. Lights 有四个 模式: add, sub, mix, 和 mask . Add 将光纹理的颜色添加到场景中. 它会照亮灯光下的区域. Sub 从场景中减去光的颜色. 它使灯光下的区域变暗. Mix 混合了灯光的颜色和底层场景. 产生的亮度介于灯光颜色和下方颜色之间. Mask 用于遮盖灯光覆盖的区域. 根据光的颜色隐藏或显示遮盖区域. Light 本身(这是灯光的效果), 和 Sprite 灯泡(一个显示光源位置的图片). 子节点 Sprite 不是让 Light 工作的必要条件.

    阴影

    Light 与 LightOccluder2D 的范围相交来制作的. Light 并在Shadows部分下面选中 启用 . Sprite 来制作 “投射影子的物体”, 但实际上您只需要几个 LightOccluder2Ds . LightOccluder2D 本身看起来像一个黑点, 在这个演示中 Sprite 只是一个黑色方块.

    渐进式教程

    既然我们已经介绍了需用到的节点的基础知识, 那就可以开始逐步实现demo中的场景了. Sprite 并将其纹理设置为 背景图片 . 在你的游戏中这可以是你选择的任何背景. 对于我们这种风格的阴影, 这张图最可能是地板的纹理. Light2D’s 并将它们的纹理设置为 light image . 你可以在上面的栏目中更改颜色. 默认情况下, 阴影关闭并且 mode 设置为 add . 这意味着每个灯光都会将自己的颜色添加到下面的任何颜色中. Light 节点添加一个 Sprite 子节点, 并将 Sprite’s 纹理设置为 blob image . 他们都应该保持在 Light 节点的中心.blob是灯本身的图像, 而 Light 显示灯光对场景的影响. LightOccluder2D’s 会将光的位置视为 Light 节点的中心, 这就是为什么我们希望blob位于父节点 Light 的中心. 注解 动画功能介绍 。 CanvasModulate 的原因. CanvasModulate 将整个视区乘以特定颜色. CanvasModulate 并将其颜色设置为 rgb(70, 70, 70) . 这将使场景足够暗, 以清楚地看到灯光的效果. 现在, 我们来添加会投射阴影的物体. Node 来组织投射阴影的物体. 在场景中添加 Node2D . 它会被用来把所有投射阴影的物体变成一个大组. 这样我们就可以同时显示和隐藏它们. LightOccluder2D 子节点的 Sprite 组成. 在演示中, Sprite 的纹理设置为 caster image . 子节点 LightOccluder2D 是所有神奇的事情发生的地方. 在游戏中 Sprite 可能不仅仅是一个黑色的方块; 它可以是任何可以投射阴影的物体的图片: 一面墙, 一个宝箱或其他任何东西. LightOccluder2Ds 告诉游戏Occluder(遮光物)是什么形状.Occluder是一个多边形的容器 OccluderPolygon2D . 对于这个演示, 由于我们的墙是正方形, 我们将 Polygon 设置为正方形. 其他设置保持为默认. Closed 可以是 onoff。 闭合的多边形遮挡来自所有方向的光线。 开放多边形仅遮挡来自一个方向的光线。 Cull Mode 让您选择剔除的方向. 默认值为 “已禁用”, 这意味着无论灯光在哪一侧, 遮挡物都会投射阴影. 另外两个设置 ClockwiseCounter-Clockwise 指的是多边形顶点的弯曲顺序. 弯曲顺序用于确定光线的哪一侧在多边形内. 只有朝外的光线才投下阴影. LightOccluder2D 的 Closed 设置为 off 的 OccluderPolygon2D . 这是为了可以看到多边形的轮廓: 注解 Cull Mode 设置为 Disabled . 全部三条轮廓线都投下阴影. 注解 Cull Mode 设置为 Clockwise . 只有顶部和右侧线条投射阴影. 注解 Cull Mode 设置为 Counter-Clockwise . 只有底部的轮廓线投下阴影. 如果 Closed 设置为 on , 左边会有一条额外的垂直轮廓线也会投射阴影. LightOccluder2Ds 时, 阴影仍不会出现. 你需要回到 Light2Ds 并在Shadow部分下设置 Enableon . 这将打开带有硬边缘的阴影, 如下图所示. filter , filter smoothgradient length . Godot支持 Percentage Closer Filtering (PCF) , 它在像素周围提取阴影贴图的多个样本, 并模糊它们以创建平滑的阴影效果. 样本数越多, 阴影看起来越平滑但运行速度越慢. 这就是为什么Godot默认提供3-13个样本并让你可以自己选择用几个样本. 该演示使用PCF7. 注解 gradient length 设置为 1.3 , filter smooth 设置成 11.1 , filter 设置为 PCF7 . 注解 filter 设置为 PCF13 . 注意这里阴影变宽了, 这是因为样本之间的距离是依赖于变量 filter smooth 的. filter smooth 变量. 这决定了样品之间的距离. 如果您想让柔软区域延伸很远, 您可以增加 filter smooth 的大小. 然而, 在低样品和大过滤平滑的情况下, 你会看到样本之间形成的线条. 注解 filter smooth 设置为 30 . Light 节点使用不同的filter smooth值. 玩玩它, 看看你喜欢什么样的. 注解 filter smooth 设置为 0 . gradient length . 对于一些平滑阴影, 最好不要在对象上立即开始阴影, 因为这会产生硬边. Gradient length(渐变长度)变量让阴影刚开始的时候平滑渐变, 以减少硬边缘的影响. 注解 gradient length 设置为 0 . 注解 gradient length 设置为 10 . filter 值越高, 阴影的计算成本也越高就行了.