gwj
4 天以前 c829b4470ea3c674565ae6288ecefb339ab873b5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
Shader "GUI/EllipseMask"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        
        [Header(Ellipse Settings)]
        _EllipseCenter ("Ellipse Center", Vector) = (0.5, 0.5, 0, 0)
        _EllipseRadius ("Ellipse Radius", Vector) = (0.5, 0.5, 0, 0)
        _Softness ("Softness", Range(0, 0.5)) = 0.1
        
        [Header(Stencil Settings)]
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 1
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
        
        _ColorMask ("Color Mask", Float) = 15
    }
 
    SubShader
    {
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "PreviewType" = "Plane"
            "CanUseSpriteAtlas" = "True"
        }
 
        // 椭圆形遮罩写入Pass
        Pass
        {
            Name "Ellipse Mask Write"
            
            Stencil
            {
                Ref [_Stencil]
                Comp Always
                Pass Replace
                ReadMask [_StencilReadMask]
                WriteMask [_StencilWriteMask]
            }
 
            ColorMask 0  // 不写入颜色,只写入模板
            ZWrite Off
            Cull Off
            Blend Off
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float2 texcoord : TEXCOORD0;
            };
 
            struct v2f
            {
                float4 vertex   : SV_POSITION;
                float2 texcoord : TEXCOORD0;
            };
 
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _EllipseCenter;
            float4 _EllipseRadius;
            float _Softness;
            
            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                // 计算到椭圆中心的距离(归一化坐标)
                float2 center = _EllipseCenter.xy;
                float2 radius = _EllipseRadius.xy;
                
                // 椭圆方程:(x-center.x)^2/radius.x^2 + (y-center.y)^2/radius.y^2 <= 1
                float2 pos = i.texcoord;
                float dx = (pos.x - center.x) / radius.x;
                float dy = (pos.y - center.y) / radius.y;
                float ellipseValue = dx * dx + dy * dy;
                
                // 软边缘处理 - 调整椭圆边界
                float adjustedEllipseValue = ellipseValue;
                if (_Softness > 0)
                {
                    // 使用smoothstep创建软边缘过渡
                    adjustedEllipseValue = smoothstep(1.0 - _Softness, 1.0 + _Softness, ellipseValue);
                }
                
                // 如果不在椭圆内,则丢弃像素
                clip(1.0 - adjustedEllipseValue - 0.01);
                return fixed4(0, 0, 0, 0);
            }
            ENDCG
        }
 
        // 正常渲染Pass - 只在模板匹配的区域渲染
        Pass
        {
            Name "Masked Content"
            
            Stencil
            {
                Ref [_Stencil]
                Comp Equal
                Pass Keep
                ReadMask [_StencilReadMask]
                WriteMask [_StencilWriteMask]
            }
 
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMask [_ColorMask]
            ZWrite Off
            Cull Off
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
 
            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
 
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            
            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.color = v.color * _Color;
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 color = tex2D(_MainTex, i.texcoord) * i.color;
                // 遮罩本身不显示颜色,只用于模板测试
                color.a = 0;
                return color;
            }
            ENDCG
        }
    }
}