lyh916

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  201 随笔 :: 0 文章 :: 12 评论 :: 21万 阅读

参考链接:

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);
        }
    }
}
复制代码

 

效果如下:

posted on   艰苦奋斗中  阅读(396)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示