参考链接:
https://blog.csdn.net/bn0305/article/details/78058076
https://www.xuanyusong.com/archives/3518
https://blog.csdn.net/wangjiangrong/article/details/79483257
Mask组件的裁剪效果,只对其下的UI元素生效,且在绘制完其下的UI元素后,所在区域的模板缓冲值会恢复为0
要想UI特效也被裁剪,可以计算scrollview四个点在世界坐标的位置,然后在粒子的shader中进行判断,如果在范围内则显示
一.shader
留意标记为add的部分
Shader "Custom/Particles/AlphaBlendedMask" { Properties { _MainTex ("Particle Texture", 2D) = "white" {} //----------------------------------------add-------------------------------- _MinX("MinX", Float) = 0 _MinY("MinY", Float) = 0 _MaxX("MaxX", Float) = 0 _MaxY("MaxY", Float) = 0 //----------------------------------------add-------------------------------- } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } Blend SrcAlpha OneMinusSrcAlpha Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //----------------------------------------add-------------------------------- float _MinX; float _MinY; float _MaxX; float _MaxY; //----------------------------------------add-------------------------------- struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; //----------------------------------------add-------------------------------- float2 worldPos : TEXCOORD1; //----------------------------------------add-------------------------------- }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); //----------------------------------------add-------------------------------- o.worldPos = mul(unity_ObjectToWorld, v.vertex).xy; //----------------------------------------add-------------------------------- return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); //----------------------------------------add-------------------------------- float posX = i.worldPos.x; float posY = i.worldPos.y; fixed result = step(_MinX, posX) * step(posX, _MaxX) * step(_MinY, posY) * step(posY, _MaxY); return result * col + (1 - result) * fixed4(0, 0, 0, 0); //----------------------------------------add-------------------------------- //return col; } ENDCG } } }
二.c#
计算scrollview四个点在世界坐标的位置
using UnityEngine; public class UIHelper : CSharpSingletion<UIHelper> { //顺时针 //1 2 //0 3 public Vector4 GetWorldCorners(GameObject go) { RectTransform rectTransform = go.GetComponent<RectTransform>(); Vector3[] corners = new Vector3[4]; rectTransform.GetWorldCorners(corners); float minX = corners[0].x; float minY = corners[0].y; float maxX = corners[2].x; float maxY = corners[2].y; return new Vector4(minX, minY, maxX, maxY); } }
设置材质
using UnityEngine; public class UIEffect : MonoBehaviour { Renderer[] renderers; MaterialPropertyBlock materialPropertyBlock; void Start() { renderers = gameObject.GetComponentsInChildren<Renderer>(); materialPropertyBlock = new MaterialPropertyBlock(); } public void SetMask(float minX, float minY, float maxX, float maxY) { for (int i = 0; i < renderers.Length; i++) { Renderer renderer = renderers[i]; materialPropertyBlock.Clear(); renderer.GetPropertyBlock(materialPropertyBlock); materialPropertyBlock.SetFloat("_MinX", minX); materialPropertyBlock.SetFloat("_MinY", minY); materialPropertyBlock.SetFloat("_MaxX", maxX); materialPropertyBlock.SetFloat("_MaxY", maxY); renderer.SetPropertyBlock(materialPropertyBlock); } } }
效果如下: