Version: 6000.3
语言: 中文
USS 过渡
USS 属性参考

USS过滤器

您可以使用 USS 过滤器来申请后期处理图像出现在屏幕上之前通过应用滤镜和效果来改善产品视觉效果的过程。您可以使用后期处理效果来模拟物理相机和胶片属性,例如泛光和景深。更多信息 后期处理、后处理、后处理
请参阅术语表
视觉元素实例化或派生自 C# 的可视化树的节点VisualElement类。您可以设置外观样式、定义行为并将其作为 UI 的一部分显示在屏幕上。更多信息
请参阅术语表
,例如模糊、色彩校正或其他自定义效果。

过滤器使用材质将效果应用于每个像素的视觉元素子树。例如,要对红色元素进行后处理,其内容和子元素将渲染为纹理,然后可以通过着色器在 GPU 上运行的程序。更多信息
请参阅术语表
. 然后,处理后的结果将重新插入到视觉元素层次结构中。您可以使用边距扩展已处理纹理的边界,以适应某些效果。在此示例中,模糊纹理具有放大的边界以适应模糊半径。

将模糊效果应用于红色元素及其子元素的过程
将模糊效果应用于红色元素及其子元素的过程

内置过滤器

UI 工具包提供了一组内置筛选器函数,可用于将常见效果应用于视觉元素。它们类似于 CSS 筛选器

filter: blur(<length>) | grayscale(<number>) | invert(<number>) | opacity(<number>) | sepia(<number>) | tint(<color>) | hue-rotate(<angle>) | contrast(<number>)

注意:该tintfunction 是特定于 Unity 的过滤器函数,它使用颜色为元素着色。CSS 不支持此函数。

USS 不支持以下 CSS 筛选器函数:

  • drop-shadow

要将过滤器应用于可视元素,请使用filter属性。USS 过滤器遵循 CSS 过滤器语法。 例如:

.builtin-blur {
    filter: blur(20px);
}

.builtin-blur-invert {
    filter: blur(5px) invert(100%);
}

以下示例演示了不同的筛选器函数效果:

原图 blur(20px) grayscale(100%) invert(100%) opacity(50%) sepia(100%) tint(#ff0000) hue-rotate(90deg) contrast(200%)
原图 模糊滤镜 灰度滤镜 反转过滤器 不透明度过滤器 棕褐色滤镜 色调滤镜 色相旋转滤镜 对比度滤镜

注意:如果您定义了多个类,并且每个类都定义了一个过滤器,并将它们应用于一个元素:最后应用的过滤器优先于前面的过滤器,而不是组合效果。例如,如果您有以下类:

.blur {
    filter: blur(20px);
}

.sepia {
    filter: sepia(100%);
}

您将这两个类都应用于一个元素 -<engine:VisualElement class="blur sepia" />- 元素仅应用了棕褐色效果。有关更多信息,请参阅选择器优先级

在 UI Builder 中应用过滤器

  1. 打开UI Builder并创建一个新的UXML文件或打开一个现有文件。
  2. 选择要应用筛选器的视觉元素。
  3. “检查器”面板中,选择“内联样式”>“筛选器”。
  4. 单击添加 (+) 按钮以添加过滤器功能。
  5. 从下拉菜单中选择内置的过滤器功能,例如blur,grayscaleinvert.
  6. 设置滤镜功能的参数,例如模糊半径或灰度百分比。

自定义过滤器

您可以创建自定义滤镜,以将所需的任何效果应用于视觉元素。

创建自定义过滤器

要创建自定义过滤器,请按照下列步骤作:

  1. 创建一个FilterFunctionDefinition资产。此资产是一个简单的ScriptableObject.

  2. 定义过滤器参数以设置过滤器的输入值。支持的过滤器参数类型包括floatcolor.在 USS 中指定时,过滤参数,例如数值、像素计算机图像中的最小单位。像素大小取决于您的屏幕分辨率。像素光照是在每个屏幕像素下计算的。更多信息
    请参阅术语表
    、百分比、持续时间和角度将转换为浮点值。参数可以在样式中设置,也可以直接在 UI 生成器中设置。例如,blur(5px)滤镜函数只有一个参数:模糊半径。这个自定义漩涡过滤器函数有两个参数,即angleradius漩涡。

  3. 提供interpolation default value(可选)。此值用于筛选器状态之间的平滑过渡。

  4. 添加效果通道。滤镜通常需要多个通道才能应用效果。例如,模糊效果通常具有单独的水平和垂直通道。滤镜中的每个效果通道包括:

  5. 要执行的材质:在 Unity 中,着色器和材质协同工作以定义表面的外观。着色器是一个程序,它告诉 GPU 如何渲染图形并确定对表面的影响。材质存储馈送到着色器的设置。

  6. 该材料的通过指数。

  7. 使用数据绑定将过滤器的参数链接到材质属性。例如,要应用色调效果,请将颜色参数直接绑定到材质的_Tint财产。对于更复杂的参数处理,请使用 C# 回调

  8. 设置边距(可选)。某些效果(例如模糊)需要纹理周围的额外空间来进行读写。如果需要,定义静态边距,或使用 C# 回调动态计算边距

有关示例,请参阅创建自定义漩涡过滤器

在 C# 代码中创建自定义筛选器

若要在 C# 中创建自定义筛选器,请定义继承自FilterFunction并添加滤镜的参数和效果。下面在 C# 中为漩涡筛选器示例创建自定义筛选器:

var customSwirl = ScriptableObject.CreateInstance<FilterFunctionDefinition>();

customSwirl.parameters = new[] {
    new FilterParameterDeclaration() {
        interpolationDefaultValue = new FilterParameter(0.0f)
    },
    new FilterParameterDeclaration() {
        interpolationDefaultValue = new FilterParameter(0.0f)
    }
};

customSwirl.passes = new[]
{
    new PostProcessingPass()
    {
        material = SwirlMaterial,
        passIndex = 0,
        parameterBindings = new[] {
            new ParameterBinding() { index = 0, name = "_Angle" },
            new ParameterBinding() { index = 1, name = "_Radius" }
        }
    }
};

在样式表中应用自定义过滤器

若要将自定义筛选器应用于可视元素,请使用 USS 文件中的 filter 属性。引用自定义过滤器资产的路径,然后引用过滤器所需的参数。例如:

.custom-effect {
    filter: filter("/Assets/Filters/CustomFilter.asset" 10px);
}

您可以在同一过滤器属性中将自定义过滤器与内置过滤器组合在一起。这允许您通过堆叠滤镜来创建复杂的视觉效果。例如:

.custom-effect-blur {
    filter: filter("/Assets/Filters/CustomFilter.asset" 10px) blur(25px);
}

在 C# 代码中应用自定义筛选器

以下示例演示如何将模糊筛选器和自定义筛选器应用于 C# 中的视觉元素:

// Create a blur filter using the built-in blur filter function
var blur = new FilterFunction(FilterFunctionType.BuiltinBlur);
blur.AddParameter(new FilterParameter(20.0f));

// Create a custom filter function definition
var custom = new FilterFunction(functionDef);
// Add parameters to the custom filter
custom.AddParameter(new FilterParameter(Color.black));

// Apply both the blur and custom filter to the visual element
element.style.filter = new List<FilterFunction> { blur, custom };

动态保证金

可以使用 C# 回调动态计算筛选器的边距。

以下 C# 代码片段为模糊函数设置动态边距。由于额外的边距取决于模糊半径,因此在这种情况下,静态边距是不够的。

在计算渲染纹理(render texture一种特殊类型的纹理,在运行时创建和更新。要使用它们,请先创建一个新的渲染纹理,并指定要渲染到其中的摄像机之一。然后,你可以在材质中使用渲染纹理,就像使用常规纹理一样。更多信息
请参阅术语表
size,则调用此回调。这允许您为给定的FilterFunction.在此示例中,模糊半径被读取为函数的第一个参数,然后用于设置边距。

effect.computeRequiredReadMarginsCallback = ComputeMargins;
effect.computeRequiredWriteMarginsCallback = ComputeMargins;

// ...

static PostProcessingMargins ComputeMargins(FilterFunction func)
{
    float radius = func.GetParameter(0).floatValue; // Blur radius value
    return new PostProcessingMargins() {
        left = radius, top = radius, right = radius, bottom = radius
    };
}

复杂参数

对于复杂参数,请使用 C# 回调。以下示例演示如何使用回调来处理筛选器参数。它将单个棕褐色量值转换为全彩矩阵。通过实现回调,您可以手动设置材质属性,而不是依赖自动参数绑定。为此,请提供一个MaterialPropertyBlock到回调,然后直接设置材质属性,绕过自动绑定过程。

effect.prepareMaterialPropertyBlockCallback = PrepareSepiaMatrix;

// ...

static void PrepareSepiaMatrix(MaterialPropertyBlock mpb, FilterFunction func)
{
    float s = func.parameters[0].floatValue; // Sepia value

    var colorMatrix = new Matrix4x4(
        new Vector4(0.393f + 0.607f * (1 - s), 0.349f - 0.349f * (1 - s), 0.272f - 0.272f * (1 - s), 0),
        new Vector4(0.769f - 0.769f * (1 - s), 0.686f + 0.314f * (1 - s), 0.534f - 0.534f * (1 - s), 0),
        new Vector4(0.189f - 0.189f * (1 - s), 0.168f - 0.168f * (1 - s), 0.131f + 0.869f * (1 - s), 0),
        new Vector4(0, 0, 0, 1));

    mpb.SetMatrix("_ColorMatrix", colorMatrix);
}

自定义滤镜UV区域

UI 工具包在应用过滤器着色器之前将过滤后的元素渲染到纹理图集中。因此,相应的 UV 坐标仅覆盖完整0–1范围。绘制滤镜时,将调整提供给片段着色器的 UV 以适合 UV 区域。在简单情况下,使用提供的UV坐标对纹理进行采样就足够了。

但是,如果你的自定义滤镜需要UV作,你需要将UV转换为0-1范围,然后返回到图集 UV 矩形。要进行转换,首先使用GetFilterRectIndex功能:

#include "UnityUIEFilter.cginc"

v2f vert (FilterVertexInput v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    o.rectIndex = GetFilterRectIndex(v); // Pass filter UV rect index to fragment shader
    return o;
}

在顶点或片段着色器中,您可以使用GetFilterUVRect函数,然后将 UV 重新映射到0-1范围:

float2 NormalizeUVs(float2 uv, float4 uvRect)
{
    // Normalize UV coordinates based on the atlas rect
    return float2(
        (uv.x - uvRect.x) / uvRect.z,
        (uv.y - uvRect.y) / uvRect.w
    );
}

float2 MapToUVRect(float2 uv, float4 uvRect)
{
    // Map UV coordinates to the atlas rect
    return float2(
        uv.x * uvRect.z + uvRect.x,
        uv.y * uvRect.w + uvRect.y
    );
}

fixed4 frag (v2f i) : SV_Target
{
    // Get the UV rect from the index
    float4 uvRect = GetFilterUVRect(i.rectIndex);

    // Convert the atlas UVs to the 0-1 range
    float2 uv = NormalizeUVs(i.uv, uvRect);

    // Do UVs manipulations, (e.g. flip Y axis)
    uv.y = 1.0f - uv.y;

    // Convert the UVs back to the atlas region
    uv = MapToUVRect(uv, uvRect);

    return tex2D(_MainTex, uv);
}

自定义筛选器和强制伽玛注意事项

在线性色彩空间中的UI工具包强制伽玛工作流程中工作时(在 面板设置(Panel Settings) 资产中启用 强制伽玛渲染(Force Gamma Rendering) 时,需要额外考虑自定义滤镜的颜色输出。在此工作流程中,最后应用的滤镜必须在输出前线性化颜色。UI Toolkit 会自动启用UIE_OUTPUT_LINEAR关键字,允许您检查此关键字以确定何时线性化颜色。请注意,这仅在强制伽玛工作流程中是必需的。

fixed4 frag(v2f IN) : SV_Target
{
    half4 col = tex2D(_MainTex, IN.uv);

    // Apply filter effect ...

    // Linearize the color for the force gamma workflow
    #if UIE_OUTPUT_LINEAR
    col.rgb = GammaToLinearSpace(col.rgb);
    #endif

    return col;
}

USS 过滤器过渡

USS 滤镜过渡遵循 CSS 滤镜过渡语法,根据滤镜属性实现流畅的视觉效果。

匹配过滤器功能

为了平滑过渡,两种状态下的筛选器函数必须完全匹配,包括函数的顺序和类型。

以下示例使用匹配的筛选器函数在两个状态之间创建平滑过渡。当您将鼠标悬停在元素上时,模糊和反转功能会平滑过渡。

.effect {
    filter: blur(0px) invert(0%);
}

.effect:hover {
    filter: blur(10px) invert(100%);
}

部分匹配的过滤器功能

当筛选器函数部分匹配时,系统会插值常用函数并应用新函数。例如,以下示例在模糊和反转函数之间进行转换。

.effect {
    filter: blur(0px); /* invert(0%) */
}

.effect:hover {
    filter: blur(10px) invert(100%);
}

在此示例中,系统使用默认插值 (0%).创建自定义过滤器时,可以在资产定义中指定插值。

不匹配的过滤器功能

如果筛选器函数在类型或顺序上不匹配(如以下示例所示),则从invert()blur()设置为blur()invert()——不会发生插值。相反,过渡会突然更改为新的筛选器状态。

.effect {
    filter: invert(0%) blur(0px);
}

.effect:hover {
    filter: blur(10px) invert(100%);
}

其他资源

USS 过渡
USS 属性参考