Up to date

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

3D 灯光和阴影

前言

光源发出灯光,灯光会与材质相混合,产生可见的结果。场景可以有很多不同类型的光源:

  • 来自材质本身的自发光颜色(但是无法影响附近的对象,除非进行了烘焙,或者启用了屏幕空间间接光照)。

  • 灯光节点:DirectionalLight3D、OmniLight3D、SpotLight3D。

  • Environment反射探针 中的环境光。

  • 全局光照(LightmapGIVoxelGISDFGI)。

自发光是材质的属性。更多相关内容见 标准 3D 材质与 ORM 3D 材质 教程。

参见

可以使用 3D 光影演示项目动态比较不同类型的灯光。

灯光节点

灯光节点有三种:DirectionalLight3DOmniLight3DSpotLight3D。让我们来看看灯光的通用参数:

../../_images/light_params.png

每个属性都有特定的功能:

  • Color:发光的基础颜色。

  • Energy:能量乘数。这对于使灯光饱和或使用 高动态范围光照 非常有用。

  • Indirect Energy:间接能量。用于间接光(反弹的光)的次级乘数。适用于 使用光照贴图全局照明、VoxelGI 和 SDFGI。

  • Volumetric Fog Energy:体积雾能量。用于体积雾的次级乘数。仅在启用体积雾时有效。

  • Negative: Light becomes subtractive instead of additive. It's sometimes useful to manually compensate some dark corners.

  • Specular:镜面反射。影响受此光影响的物体中镜面反射斑点的强度。值为零时,该光变为纯漫反射光。

  • Bake Mode:设置灯光的烘焙模式。见 使用光照贴图全局照明

  • Cull Mask: Objects that are in the selected layers below will be affected by this light. Note that objects disabled via this cull mask will still cast shadows. If you don't want disabled objects to cast shadows, adjust the Cast Shadow property on the GeometryInstance3D to the desired value.

参见

如果你希望使用真实世界的单位来配置灯光的强度和色温,请参阅 物理灯光和相机单位

Light number limits

When using the Forward+ renderer, Godot uses a clustering approach for real-time lighting. As many lights as desired can be added (as long as performance allows). However, there's still a default limit of 512 clustered elements that can be present in the current camera view. A clustered element is an omni light, a spot light, a decal or a reflection probe. This limit can be increased by adjusting the Rendering > Limits > Cluster Builder > Max Clustered Elements advanced project setting.

When using the Forward Mobile renderer, there is a limitation of 8 OmniLights + 8 SpotLights per mesh resource. There is also a limit of 256 OmniLights + 256 SpotLights that can be rendered in the current camera view. These limits currently cannot be changed.

When using the Compatibility renderer, up to 8 OmniLights + 8 SpotLights can be rendered per mesh resource. This limit can be increased in the advanced Project Settings by adjusting Rendering > Limits > OpenGL > Max Renderable Lights and/or Rendering > Limits > OpenGL > Max Lights Per Object at the cost of performance and longer shader compilation times. The limit can also be decreased to reduce shader compilation times and improve performance slightly.

在所有的渲染方法中,最多可以同时显示 8 个方向灯。但是,每增加一个启用阴影的定向灯,都会降低每个定向灯的有效阴影分辨率。这是因为所有灯光共享方向阴影atlas。

If the rendering limit is exceeded, lights will start popping in and out during camera movement, which can be distracting. Enabling Distance Fade on light nodes can help reduce this issue while also improving performance. Splitting your meshes into smaller portions can also help, especially for level geometry (which also improves culling efficiency).

如果你需要渲染的灯光数量超过了给定渲染后端所能提供的数量,请考虑使用 baked lightmaps,并将灯光的烘焙模式设置为 Static。这样就可以完全烘焙光照,从而加快渲染速度。你也可以使用任何全局光照技术的自发光材料来替代在大范围内发出光线的光节点。

阴影贴图

灯光可以可选地投射阴影. 这使它们具有更好的真实感(光线不会照到被遮挡的区域), 但它会带来更大的性能开销. 有一个通用阴影参数列表, 每个参数也有一个特定的功能:

  • Enabled: Check to enable shadow mapping in this light.

  • Opacity: Areas occluded are darkened by this opacity factor. Shadows are fully opaque by default, but this can be changed to make shadows translucent for a given light.

  • Bias: When this parameter is too low, self-shadowing occurs. When too high, shadows separate from the casters. Tweak to what works best for you.

  • Normal Bias: When this parameter is too low, self-shadowing occurs. When too high, shadows appear misaligned from the casters. Tweak to what works best for you.

  • Transmittance Bias: When this parameter is too low, self-shadowing occurs on materials that have transmittance enabled. When too high, shadows will not affect materials that have transmittance enabled consistently. Tweak to what works best for you.

  • Reverse Cull Face: Some scenes work better when shadow mapping is rendered with face-culling inverted.

  • Blur: Multiplies the shadow blur radius for this light. This works with both traditional shadow mapping and contact-hardening shadows (lights with Angular Distance or Size greater than 0.0). Higher values result in softer shadows, which will also appear to be more temporally stable for moving objects. The downside of increasing shadow blur is that it will make the grainy pattern used for filtering more noticeable. See also 阴影过滤模式.

../../_images/lights_and_shadows_blur.webp

Tweaking shadow bias

Below is an image of what tweaking bias looks like. Default values work for most cases, but in general, it depends on the size and complexity of geometry.

If the Shadow Bias or Shadow Normal Bias is set too low for a given light, the shadow will be "smeared" onto the objects. This will cause the light's intended appearance to darken, and is called shadow acne:

../../_images/lights_and_shadows_acne.webp

On the other hand, if the Shadow Bias or Shadow Normal Bias is set too high for a given light, the shadow may appear to be disconnected from the object. This is called peter-panning:

../../_images/lights_and_shadows_peter_panning.webp

In general, increasing Shadow Normal Bias is preferred over increasing Shadow Bias. Increasing Shadow Normal Bias does not cause as much peter-panning as increasing Shadow Bias, but it can still resolve most shadow acne issues efficiently. The downside of increasing Shadow Normal Bias is that it can make shadows appear thinner for certain objects.

Any sort of bias issues can be fixed by increasing the shadow map resolution, at the cost of decreased performance.

备注

Tweaking shadow mapping settings is an art – there are no "one size fits all" settings. To achieve the best visuals, you may need to use different shadow bias values on a per-light basis.

平行光

这是最常见的光线类型, 代表了很远的光源(如太阳). 它也是计算中最便宜的光, 应该尽可能使用(虽然它不是计算起来最便宜的阴影贴图, 但这点稍后再说).

平行光模拟覆盖整个场景的无限数量的平行光线。平行光节点由指示光线方向的大箭头表示。但是,节点的位置根本不会影响照明,它可以在任何地方。

../../_images/light_directional.png

Every face whose front-side is hit by the light rays is lit, while the others stay dark. Unlike most other light types directional lights, don't have specific parameters.

The directional light also offers a Angular Distance property, which determines the light's angular size in degrees. Increasing this above 0.0 will make shadows softer at greater distances from the caster, while also affecting the sun's appearance in procedural sky materials. This is called a contact-hardening shadow (also known as PCSS).

作为参考,从地球看太阳的角距离约为 0.5 。这种阴影的性能开销比较高昂,因此如果在启用阴影的灯光上将此值设置为高于 0.0 ,请查看 PCSS 建议 中的建议。

方向光阴影贴图

To compute shadow maps, the scene is rendered (only depth) from an orthogonal point of view that covers the whole scene (or up to the max distance). There is, however, a problem with this approach because objects closer to the camera receive low-resolution shadows that may appear blocky.

To fix this, a technique named Parallel Split Shadow Maps (PSSM) is used. This splits the view frustum in 2 or 4 areas. Each area gets its own shadow map. This allows small areas close to the viewer to have the same shadow resolution as a huge, far-away area.

../../_images/lights_and_shadows_pssm_explained.webp

有了它, 阴影变得更加详细:

../../_images/lights_and_shadows_directional_mode.webp

为了控制PSSM, 暴露了许多参数:

../../_images/lights_and_shadows_directional_shadow_params.webp

Each split distance is controlled relative to the camera far (or shadow Max Distance if greater than 0.0). 0.0 is the eye position and 1.0 is where the shadow ends at a distance. Splits are in-between. Default values generally work well, but tweaking the first split a bit is common to give more detail to close objects (like a character in a third-person game).

Always make sure to set a shadow Max Distance according to what the scene needs. A lower maximum distance will result in better-looking shadows and better performance, as fewer objects will need to be included in shadow rendering. You can also adjust Fade Start to control how aggressive the shadow fade-out should be at a distance. For scenes where the Max Distance fully covers the scene at any given camera position, you can increase Fade Start to 1.0 to prevent the shadow from fading at a distance. This should not be done in scenes where Max Distance doesn't fully cover the scene, as the shadow will appear to be suddenly cut off at a distance.

Sometimes, the transition between a split and the next can look bad. To fix this, the Blend Splits option can be turned on, which sacrifices detail and performance in exchange for smoother transitions:

../../_images/blend_splits.png

The Shadow > Normal Bias parameter can be used to fix special cases of self-shadowing when objects are perpendicular to the light. The only downside is that it makes the shadow a bit thinner. Consider increasing Shadow > Normal Bias before increasing Shadow > Bias in most situations.

Lastly, Pancake Size is a property that can be adjusted to fix missing shadows when using large objects with unsubdivided meshes. Only change this value if you notice missing shadows that are not related to shadow biasing issues.

全向光

全向光是一种点光源,可在所有方向上发射光,直至给定的半径。

../../_images/light_omni.png

在现实生活中,光衰减是个和距离成反比的函数,这意味着全向光没有半径。这是一个问题,因为这意味着计算几个全向光会变得很困难。

To solve this, a Range parameter is introduced together with an attenuation function.

../../_images/light_omni_params.png

这两个参数允许调整其在视觉上的工作方式, 以便找到美学上令人愉悦的结果.

../../_images/light_attenuation.png

OmniLight3D 中还有一个 Size 参数。增大该值会使光线减弱得更慢,在远离投射者时阴影会显得更模糊。这可以在一定程度上模拟区域灯光。这就是 接触硬化 (contact-hardening)阴影(也称为 PCSS)。这种阴影的成本较高,因此在启用阴影的灯光上将此值设置为高于 0.0 时,请查看 PCSS 建议 中的建议。

../../_images/lights_and_shadows_pcss.webp

全向光阴影贴图

全向光的阴影贴图相对简单。需要考虑的主要问题是用于渲染它的算法。

Omni Shadows can be rendered as either Dual Paraboloid or Cube mapped. Dual Parabolid renders quickly, but can cause deformations, while Cube is more correct, but slower. The default is Cube, but consider changing it to Dual Parabolid for lights where it doesn't make much of a visual difference.

../../_images/lights_and_shadows_dual_parabolid_vs_cubemap.webp

If the objects being rendered are mostly irregular and subdivided, Dual Paraboloid is usually enough. In any case, as these shadows are cached in a shadow atlas (more on that at the end), it may not make a difference in performance for most scenes.

启用阴影功能的全向灯光可以使用投影。投影纹理会将灯光的颜色乘以纹理上给定点的颜色。因此,一旦分配了投影纹理,灯光通常会显得更暗;你可以增加 Energy 来弥补这一点。

全方位光投影纹理需要特殊的 360° 全景贴图,类似于 PanoramaSkyMaterial 纹理。

通过下面的投影纹理,可以得到以下结果:

../../_images/lights_and_shadows_omni_projector_example.webp ../../_images/lights_and_shadows_omni_projector.webp

小技巧

If you've acquired omni projectors in the form of cubemap images, you can use this web-based conversion tool to convert them to a single panorama image.

聚光

聚光与全向光类似,但是它们只发光到锥形(或“截断”)中。它们可用于模拟手电筒、车灯、反射器、聚光灯等。这种类型的光也会向其指向的相反方向衰减。

Spot lights share the same Range, Attenuation and Size as OmniLight3D, and add two extra parameters:

  • Angle(角度) : 光线的光圈角度。

  • Angle Attenuation: The cone attenuation, which helps soften the cone borders.

聚光灯阴影贴图

聚光灯的阴影贴图参数与全方位光源相同。由于只需渲染一个阴影纹理(而不是渲染 6 个面,或在双 Parabolid 模式下渲染 2 个面),因此渲染聚光灯阴影贴图的速度明显快于全方位光源。

启用阴影功能的光线可以使用投影。投影纹理会将灯光的颜色乘以纹理上给定点的颜色。因此,一旦分配了投影纹理,灯光通常会显得更暗;你可以增加 Energy 来弥补这一点。

与全向光投影不同,聚光灯投影纹理不需要遵循特殊格式就能看起来正确无误。它的映射方式类似于 decal

通过下面的投影纹理,可以得到以下结果:

../../_images/lights_and_shadows_spot_projector_example.webp ../../_images/lights_and_shadows_spot_projector.webp

备注

广角聚光灯的阴影质量会低于窄角聚光,因为阴影贴图会分布在更大的表面上。角度大于 89 度时,聚光阴影将完全停止工作。如果你需要更宽的灯光阴影,请使用全向光。

影子图集

Unlike Directional lights, which have their own shadow texture, omni and spot lights are assigned to slots of a shadow atlas. This atlas can be configured in the advanced Project Settings (Rendering > Lights And Shadows > Positional Shadow).

The resolution applies to the whole shadow atlas. This atlas is divided into four quadrants:

../../_images/lights_and_shadows_shadow_quadrants.webp

每个象限可以细分,分配任意数量的阴影贴图。以下是默认细分方式:

../../_images/lights_and_shadows_shadow_quadrants2.webp

The shadow atlas allocates space as follows:

  • The biggest shadow map size (when no subdivision is used) represents a light the size of the screen (or bigger).

  • Subdivisions (smaller maps) represent shadows for lights that are further away from view and proportionally smaller.

每一帧, 以下过程被应用于所有光:

  1. 检查灯光是否在正确大小的插槽上. 如果没有, 重新渲染它并将其移动到更大/更小的插槽.

  2. 检查影响阴影贴图的任何对象是否已更改. 如果是的话, 重新渲染光线.

  3. 如果上述情况均未发生, 则不执行任何操作, 阴影保持不变.

If the slots in a quadrant are full, lights are pushed back to smaller slots, depending on size and distance. If all slots in all quadrants are full, some lights will not be able to render shadows even if shadows are enabled on them.

默认的阴影分配策略最多可以渲染 88 盏灯,并在相机锥体中启用阴影(4 + 4 + 16 + 64):

  1. 第一象限也是最精细的象限,可以存储 4 个阴影。

  2. 第二象限可存储 4 个其他阴影。

  3. 第三象限可存储 16 个阴影,但细节较少。

  4. 第四象限也是细节最少的象限,可存储 64 个阴影,但细节更少。

每个象限使用较多的阴影数量可以支持启用阴影的更多灯光,同时还能提高性能(因为阴影将以较低的分辨率为每个灯光渲染)。不过,增加每个象限的阴影数量的代价是降低阴影质量。

In some cases, you may want to use a different allocation strategy. For example, in a top-down game where all lights are around the same size, you may want to set all quadrants to have the same subdivision so that all lights have shadows of similar quality level.

平衡性能与质量

阴影渲染是 3D 渲染性能方面的重要议题。做出正确的选择非常重要,这样才能避免制造出瓶颈。

平行光的阴影质量设置可以在运行时调整,调用合适的 RenderingServer 方法即可。

位置光(全向灯/聚光灯)的阴影质量设置可以在运行时调整,设置根 Viewport 即可。

阴影贴图大小

高阴影分辨率会带来更清晰的阴影,但会付出很大的性能代价。还需要注意的是,更清晰的阴影并不总是更逼真。在大多数情况下,应将其保持在默认值 4096,或将低端 GPU 的默认值降至 2048

如果在减小阴影贴图大小后,位置阴影变得过于模糊,可以通过调整 shadow atlas 象限以包含较少的阴影来解决。这样就能以更高的分辨率渲染每个阴影。

阴影过滤模式

这里可以选择多种阴影贴图质量设置。默认的**Soft Low**在性能和质量之间取得了很好的平衡,适用于有细节纹理的场景,因为纹理细节有助于使颜色抖动的纹路不那么明显。

However, in projects with less detailed textures, the shadow dithering pattern may be more visible. To hide this pattern, you can either enable 时间抗锯齿(TAA), AMD FidelityFX Super Resolution 2.2 (FSR2), 快速近似抗锯齿(FXAA), or increase the shadow filter quality to Soft Medium or higher.

Soft Very Low 设置会自动减少阴影模糊,使低采样数产生的伪影不那么明显。相反,Soft HighSoft Ultra 设置会自动增加阴影模糊,以更好地利用增加的样本数。

../../_images/lights_and_shadows_filter_quality.webp

16 位与 32 位

默认情况下,Godot 使用 16 位深度纹理进行阴影贴图渲染。在大多数情况下,我们都建议使用这种方式,因为它的性能更好,而且质量也不会有明显差异。

如果禁用**16 Bits**,则将使用 32 -bits深度纹理。这可以减少大型场景和启用阴影的大型灯光中的伪影。不过,这种差异通常几乎不明显,但却会带来显著的性能损失。

灯光/阴影的距离淡出

OmniLight3D 和 SpotLight3D 提供了一些能够隐藏远距离灯光的属性。如果是在大型场景中,并且存在几十盏灯,就能够显著提升性能。

  • Enabled: Controls whether distance fade (a form of LOD) is enabled. The light will fade out over Begin + Length, after which it will be culled and not sent to the shader at all. Use this to reduce the number of active lights in a scene and thus improve performance.

  • Begin: The distance from the camera at which the light begins to fade away (in 3D units).

  • Shadow: The distance from the camera at which the shadow begins to fade away (in 3D units). This can be used to fade out shadows sooner compared to the light, further improving performance. Only available if shadows are enabled for the light.

  • Length: The distance over which the light and shadow fades (in 3D units). The light becomes slowly more transparent over this distance and is completely invisible at the end. Higher values result in a smoother fade-out transition, which is more suited when the camera moves fast.

PCSS 建议

Percentage-closer soft shadows (PCSS) provide a more realistic shadow mapping appearance, with the penumbra size varying depending on the distance between the caster and the surface receiving the shadow. This comes at a high performance cost, especially for directional lights.

为了避免性能问题,建议:

  • 仅在给定时间里使用少量启用了 PCSS 阴影的灯光。 这种效果通常在大而明亮的灯光下最为明显。 较微弱的辅助光源通常不会从使用 PCSS 阴影中获益。

  • 为用户提供禁用 PCSS 阴影的设置。 在平行光上,这可以通过在脚本中将 DirectionalLight3D 的 light_angular_distance 属性设置为 0.0 来完成。 对于位置光源,这可以通过在脚本中将 OmniLight3D 或 SpotLight3D 的 light_size 属性设置为 0.0 来完成。

投影器过滤模式

投影的渲染方式也会对性能产生影响。 渲染> 纹理 > 光投影器 > 过滤 高级项目设置可让你控制投影纹理的过滤方式。 Nearest/Linear 不使用 mipmap,这会使得渲染速度更快。 然而,投影在远处看起来会有颗粒感。 Nearest/Linear Mipmaps 在远处看起来会更平滑,但从倾斜角度观看时投影会看起来模糊。 这可以通过使用 Nearest/Linear Mipmaps Anisotropic 来解决,这是最高质量的模式,但也是消耗最大的。

如果你的项目具有像素艺术风格,请考虑将过滤器设置为 Nearest 的值之一,以便投影使用最近邻过滤(nearest-neighbor filtering)。 否则,请继续使用 Linear