对 2D UI 元素(如 Image、RawImage、Text)进行矩形区域裁剪,隐藏超出矩形范围的部分。

使用方法

添加组件

RectMask2D 的工作原理是通过将裁剪矩形 _ClipRect 传递给子物体所使用的 Shader 来实现裁剪的,故首先需要添加RectMask2D组件作为父级。 在Shader代码中可添加变体UNITY_UI_CLIP_RECT来处理RectMask2D裁剪相关的逻辑:

HLSL
#pragma multi_compile _ UNITY_UI_CLIP_RECT
点击展开查看更多

声明变量

直接声明变量_ClipRect不需要定义属性(Properties)

HLSL
float4 _ClipRect;
点击展开查看更多

变量含义:矩形裁剪区域坐标(模型空间)(xMin, yMin, xMax, yMax)

实现裁剪

核心思路:根据坐标判断在裁剪区域内的像素保留,区域外的剔除。

HLSL
#ifdef UNITY_UI_CLIP_RECT
	if(IN.positionOS.x > _ClipRect.x && IN.positionOS.y > _ClipRect.y && IN.positionOS.x < _ClipRect.z && IN.positionOS.y < _ClipRect.w)
		clip(0);
	else
		clip(-1);
#endif
点击展开查看更多

使用step函数

HLSL
#ifdef UNITY_UI_CLIP_RECT
	float2 r = step(_ClipRect.xy, IN.positionOS.xy) * step(IN.positionOS.xy, _ClipRect.zw);
	clip(r.x * r.y - 1);
#endif
点击展开查看更多

使用内置函数:UnityGet2DClipping 需要引入UnityUI.cginc,该函数的实现就是step法

HLSL
#include "UnityUI.cginc" // 引入库
// ...
{
	#ifdef UNITY_UI_CLIP_RECT
		clip(UnityGet2DClipping(IN.positionOS, _ClipRect) - 1);
	#endif
}
点击展开查看更多

RectMask2D 与 Mask

特性 RectMask2D Mask
原理 GPU 裁剪 Stencil 模板缓冲区
额外DrawCall 有(模板生成+遮罩渲染)
填充率开销 低(仅逐像素裁剪计算) 中高(需模板读写)
非矩形支持 ❌ 仅支持矩形 ✅ 支持任意形状
锯齿边缘 硬边缘 可抗锯齿

注意事项

  1. RectMask2D嵌套: 当多个RectMask2D嵌套时,裁剪区域取交集
  2. 内置Shader: 使用内置 UI Shader(如 UI/Default) 自动支持RectMask2D。

完整例子

SHADERLAB
Shader "ChaimLearn/UIShader"
{
    Properties { }
    
    SubShader
    {
        Tags { "Queue" = "Transparent" }
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ UNITY_UI_CLIP_RECT
            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            float4 _ClipRect; // 声明变量

            struct Varyings {
                float4 positionOS: TEXCOORD0;
                float4 positionCS: SV_POSITION;
            };

            Varyings vert(float4 positionOS: POSITION) {
                Varyings OUT;
                OUT.positionOS = positionOS;
                OUT.positionCS = UnityObjectToClipPos(positionOS);
                return OUT;
            }

            half4 frag(Varyings IN): SV_TARGET {
                #ifdef UNITY_UI_CLIP_RECT
                    clip(UnityGet2DClipping(IN.positionOS, _ClipRect) - 1);
                #endif
                return 1;
            }
            ENDHLSL
        }
    }
}
点击展开查看更多

版权声明

作者: Chaim

链接: https://chaim.eu.org/posts/rect-mask-2d/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键