阴影映射
简介
阴影映射是一种为 3D 场景提供实时阴影的常用技术。其工作原理是从光源的视角渲染一张深度图纹理。 然后,在对 3D 模型的像素进行着色时,将其深度值与深度图进行比较,如果处于阴影中,则着色更暗;如果受到光源照射,则着色更亮。
阴影增加了场景的视觉真实感,并使判断物体的相对位置变得更加容易。

请注意,在图片左侧的场景中,无法判断物体距离平面的距离,但在右侧场景中,阴影使这一点变得显而易见。
Qt 为我们的三种光源类型(DirectionalLight 、PointLight 和SpotLight )都提供了阴影映射支持。要在场景中启用阴影,首先需要将castsShadow 设置为true ,使光源能够投射阴影。然后,您可以通过将castsShadows 和receivesShadows 分别设置为true 或false ,来控制哪些模型会投射和接收阴影。
定向光源
定向光源从位于无限远处的不可识别光源处向一个方向发射光线。这类似于现实生活中阳光的作用方式。定向光源的照射范围无限,且光强不会衰减。
级联阴影贴图
DirectionalLight (阴影贴图)的一个问题在于,它会从光源的视角渲染整个场景。当阴影贴图的大小不足时,这可能会导致阴影看起来呈块状。要获得更好的渲染质量,一种选择是使用级联阴影贴图(CSM)。 Qt 支持一种名为“并行分割阴影贴图”(PSSM)的 CSM 变体。PSSM 的工作原理是将视锥体分割为若干部分,并为每个部分渲染一张阴影贴图。

这张图展示了一个采用 PSSM 分割的视锥体的抽象示意图。它包含两个分割点,最终形成三个级联。
通过这种方式,可以在靠近摄像机且视觉质量更易察觉的区域获得更高的阴影贴图分辨率,而在远离摄像机且视觉质量较不明显的区域则采用较低的分辨率。

上图展示了未进行任何分割的阴影贴图(左)和进行了3次分割的阴影贴图(右)。
您可以通过csmNumSplits 属性控制级联分割的数量,并通过csmSplit1 、csmSplit2 和csmSplit3 属性控制分割的位置。为了在分割点之间获得平滑的过渡,您可以使用csmBlendRatio 属性指定它们之间的混合程度。

上图展示了未启用混合效果的级联接缝的放大视图。
请注意,每增加一个分割,应用程序就必须渲染另一张阴影贴图,这会对性能产生负面影响。混合区域的大小会影响性能,因此请将其设置得尽可能小。
点光源
PointLight 可以描述为一个球体,从光源中心向各个方向以相等的强度发射光线,射程可达给定的半径。这类似于灯泡发光的方式。

PointLight 会将其阴影贴图渲染为立方贴图,这意味着需要进行六次渲染迭代。这在计算上可能相当耗时。
聚光灯
SpotLight 以锥形向一个方向发射光线,其方向由coneAngle 属性定义。当光线接近coneAngle 时,光强会逐渐减弱。光强开始减弱的角度由innerConeAngle 定义。这类似于手电筒或聚光灯的发光方式。

与PointLight 不同,SpotLight 将其阴影贴图渲染到单个深度贴图中。
性能与场景调整
虽然 Qt 会为与阴影映射相关的属性提供合理的默认值,但通常仍需要根据具体场景进行调整。特别是当场景的规模远小于或远大于预期时。 下一节将详细介绍如何调整这些参数,既能使阴影贴图效果良好,又能尽可能保持良好的性能。
阴影偏移
Shadow bias 是一种消除所谓“阴影痘”的方法,即通常以特定图案出现的虚假阴影。阴影偏移通过偏移阴影贴图的深度纹理,使阴影看起来离投射物体更远,这通常可以解决“阴影痘”问题。 其缺点在于,如果阴影偏移量过大,可能会产生一种称为“彼得·潘效应”的现象,即阴影与投影物体之间的距离过远。此外,通过提高阴影贴图的分辨率,也可以减少阴影痘。

上图展示了阴影偏移量为 0(左)与 10(右)时的场景对比。左侧场景中,锥体和圆柱体的顶部存在一些虚假阴影。
阴影贴图分辨率
阴影贴图的分辨率/质量由shadowMapQuality 属性控制。较高的阴影贴图质量可以减少阴影的块状感,但渲染开销更大,因此应将其设置为尽可能低,同时仍能保持所需的视觉质量。

上图展示了低阴影贴图分辨率与高阴影贴图分辨率下的场景对比。
柔和阴影质量
柔和阴影是一种模拟现实生活中阴影效果的方法,即阴影从边缘的锐利逐渐过渡到柔和。柔和阴影的质量由softShadowQuality 属性控制。该属性既支持无柔和度的硬阴影,也支持不同质量级别的百分比邻近过滤(PCF)柔和阴影。 硬阴影的渲染成本最低,而PCF的质量越高,渲染成本就越高。要控制柔和阴影的半径,请使用pcfFactor 属性。pcfFactor 的数值不会影响渲染速度,但数值越高,为获得良好的视觉效果所需的柔和阴影质量就越高。

上图左侧展示了一个使用softShadowQuality 的Light.Hard 阴影的场景,右侧则展示了一个使用softShadowQuality 的Light.PCF32 以及pcfFactor 的10 的场景。
阴影贴图远距离
shadowMapFar 属性可用于控制阴影贴图的最大距离。该属性在PointLight 和SpotLight 与DirectionalLight 中的工作方式略有不同。
对于PointLight/SpotLight ,它决定渲染阴影的包围盒大小;而对于DirectionalLight ,它定义了阴影贴图在场景中应覆盖的、距离场景摄像机多远的范围。

上图展示了同一场景、同一方向光,但shadowMapFar 的两个不同数值。
阴影贴图位深度
在某些情况下,场景规模非常庞大,导致阴影贴图在深度轴上覆盖的范围很大。例如,当有许多远离摄像机视场的物体仍在投射阴影,且需要包含在阴影贴图边界内时。 这种情况下,即使将shadowBias 设置得更高,场景中仍可能出现条带状伪影。解决此问题的一种方法是使用32位深度的阴影贴图。将use32BitShadowmap 属性设置为true 即可在特定光源上启用此功能。

上图展示了同一场景下的相同定向光效果,其中一个使用了 32 位阴影贴图,另一个则使用了 16 位阴影贴图。
另请参阅 《使用基于图像的照明》、《光照贴图与全局光照》以及《Qt Quick 3D ——级联阴影贴图示例》。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.