在 Windows UI 中使用光

Windows.UI.Composition API 使你可以创建实时动画和效果。 合成光线可在 2D 应用程序中实现 3D 照明。 在此概述中,我们将详细描述如何设置合成光线、标识要接收每种光的视觉对象以及使用各种效果为内容定义材料。

注意

若要了解 XamlLight 对象如何应用 CompositionLights 以照亮 XAML UIElement,请参阅 XAML 照明

使用合成光线可以通过允许实现以下功能来创建有趣的 UI:

  • 独立于场景中其他对象的光转换,可实现沉浸式方案,如音乐播放场景。
  • 能够将对象与光配对,以便它们独立于场景的其余部分一起移动,以实现 Fluent 突出显示这类方案。
  • 将光和整个场景作为一个组进行转换,以创建材料和深度。

合成光线支持三个关键概念:光、目标和 SceneLightingEffect

浅色

CompositionLight 使你可以创建各种光,并将其置于坐标空间中。 这些光的目标是你希望识别为被光照亮的视觉对象。

光类型

类型 描述
AmbientLight 发出看上去被场景中所有对象反射的非定向光的光源。
遥远的光 在一个方向上发出光的无限远的光源。 类似于太阳。
PointLight 在所有方向上发出光的点光源。 类似于灯泡。
聚光灯 发出内部和外部光锥的光源。 类似于闪光灯。

目标

当光以某个视觉对象(添加到目标列表)为目标时,该视觉对象及其所有后代都可感知和响应此光源。 这可以十分简单,比如在树的根处设置 PointLight 源,下面的所有视觉对象都会对点光方向的动画进行反应。

ExclusionsFromTargets 使你能够以类似于添加目标的方式删除视觉对象或视觉对象子树的照明。 因此,不会照亮以被排除的视觉对象作为根的树中的子级。

示例(目标)

在下面的示例中,我们使用 CompositionPointLight 将 XAML TextBlock 作为目标。

    _pointLight = _compositor.CreatePointLight();
    _pointLight.Color = Colors.White;
    _pointLight.CoordinateSpace = text; //set up co-ordinate space for offset
    _pointLight.Targets.Add(text); //target XAML TextBlock

通过将动画添加到点光的偏移量,可轻松实现闪现效果。

_pointLight.Offset = new Vector3(-(float)TextBlock.ActualWidth, (float)TextBlock.ActualHeight / 2, (float)TextBlock.FontSize);

请参阅 GitHub 上的完整 文本填充 示例,了解详细信息。

限制

确定 CompositionLight 将照亮的内容时,有几个因素需要考虑。

概念 详细信息
环境光 将非环境光源添加到场景会关闭所有现有光。 不是作为非环境光目标的项会显示为黑色。 若要以自然的方式照亮不是作为光目标的周围视觉对象,请将环境光与其他光结合使用。
光的数量 你可以使用任意组合的任意两个非环境合成光将你的 UI 作为目标。 环境光不受限制;投射光、点光和平行光会受限制。
生存期 CompositionLight 可能会遇到生存期条件(示例:垃圾回收器可能会在使用光对象之前回收该对象)。 建议将灯添加为成员来帮助应用程序管理生存期,从而保留对光的引用。
转换 光必须置于 UI 之上的节点中,该节点在视觉对象结构中使用透视转换等效果以正确绘制。
目标和坐标空间 CoordinateSpace 是必须在其中设置所有光属性的视觉对象空间。 CompositionLight.Targets 必须处于 CoordinateSpace 树中。

照明属性

根据所用的光类型,光可以具有衰减和空间方面的属性。 并非所有光类型都使用所有属性。

properties 描述
颜色 光的颜色。 照明颜色值由 D3D 漫射、环境和镜面进行定义,这些值定义所发出的颜色。 照明为光使用 RGBA 值;不使用 Alpha 颜色分量。
方向 光的方向。 光指向的方向相对于其 CoordinateSpace 视觉对象进行指定。
坐标空间 每个视觉对象都有一个隐式 3D 坐标空间。 X 方向是从左到右。 Y 方向是从上到下。 Z 方向是平面外的点。 此坐标的原点是视觉对象的左上角,单位是与设备无关的像素 (DIP)。 光的偏移量在此坐标中进行定义。
内锥和外锥 聚光发出的光锥包括两个部分:一个明亮的内锥和一个外锥。 合成使你可以控制内锥和外锥角度和颜色。
偏移量 光源相对于其坐标空间视觉对象的偏移量。

注意

当多个光命中相同视觉对象时,或者每当光的颜色值大到足以超过 1.0 时,光的颜色可能会改变,因为光颜色通道会固定住。

高级照明属性

properties 描述
强度 控制光的亮度。
衰减 衰减控制光的强度如何随距离属性指定的最大距离而减弱。 可以使用常量、二次和线性衰减属性。

照明入门

请按照以下常规步骤添加光:

  • 创建和放置光:创建光并将其放在指定坐标空间中。
  • 标识要照亮的对象:使光将相关视觉对象作为目标。
  • [可选] 定义各个对象对光的反应方式:将 SceneLightingEffect 与 EffectBrush 配合使用,以自定义用于显示 SpriteVisual 的光反射。 反射默认值支持光源的 CoordinateSpace 的子级照明。 使用 SceneLightingEffect 绘制的视觉对象会覆盖该视觉对象的默认照明。

场景照明效果

SceneLightingEffect 用于修改应用于作为 CompositionLight 目标的 SpriteVisual 内容的默认照明。

SceneLightingEffect 经常用于材料创建。 SceneLightingEffect 是一种在实现更复杂的内容(例如,在图像上启用反射属性和/或通过法线贴图提供深度幻觉)时使用的效果。 通过 SceneLightingEffect 能够使用照明属性(如镜面量和漫射量)自定义 UI。 可以使用效果管道的其余部分进一步自定义照明效果,从而可以单独将不同的照明反应与内容混合并组合在一起。

注意

场景照明不会产生阴影;它是一种侧重于 2D 呈现的效果。 它不考虑包含真实照明模型(包括阴影)的 3D 照明方案。

properties 描述
法线贴图 NormalMap 会创建纹理效果,其中指向光的法线会变亮,而指向远处的法线会变暗。 若要将 NormalMap 添加到目标视觉对象,请使用 CompositionSurfaceBrush(使用 LoadedImageSurface 加载 NormalMap 资产)。
环境 环境属性主要用于控制整体颜色反射。
反射 镜面反射在对象上创建突出显示,使其看上去闪亮。 可以控制镜面反射的级别以及照耀级别。 操作这些属性可创建材料效果,如闪亮金属或光泽纸。
漫射 漫反射会将光分散到所有方向。
反射模型 反射模型使你可以在 Blinn Phong 和基于物理的 Blinn Phong 之间进行选择。 当你希望具有压缩镜面突出显示时,可以选择基于物理的 Blinn Phong。

示例 (SceneLightingEffect)

下面的示例演示如何将法线贴图添加到 SceneLightingEffect。

CompositionBrush CreateNormalMapBrush(ICompositionSurface normalMapImage)
{
    var colorSourceEffect = new ColorSourceEffect()
    {
        Color = Colors.White
    };
    var sceneLightingEffect = new SceneLightingEffect()
    {
        NormalMapSource = new CompositionEffectSourceParameter("NormalMap")
    };

    var compositeEffect = new ArithmeticCompositeEffect()
    {
        Source1 = colorSourceEffect,
        Source2 = sceneLightingEffect,
    };

    var factory = _compositor.CreateEffectFactory(sceneLightingEffect);

    var normalMapBrush = _compositor.CreateSurfaceBrush();
    normalMapBrush.Surface = normalMapImage;
    normalMapBrush.Stretch = CompositionStretch.Fill;

    var brush = factory.CreateBrush();
    brush.SetSourceParameter("NormalMap", normalMapBrush);

    return brush;
}