untiy UIPanel 裁剪

来源:互联网 发布:学什么软件好找工作 编辑:程序博客网 时间:2024/06/05 19:56

使用 unity 做游戏开发时,有时需要在scroll view下使用粒子,但粒子是不会被 UIPanel 所裁剪的,本人提供了脚本 ParticleSystemClipper,用来处理这种情况。思路是,通过 UIPanel 的 finalClipRegion 换算成 unity3d 世界坐标系中的区域,然后传递到粒子的 shader 中进行裁剪。代码如下:

复制代码
using System;using UnityEngine;[RequireComponent(typeof(UIPanel))]public class ParticleSystemClipper : MonoBehaviour{    const string ShaderName = "Bleach/Particles Additive Area Clip";    const float ClipInterval = 0.5f;    UIPanel m_targetPanel;    Shader m_shader;    void Start()    {        // find panel        m_targetPanel = GetComponent<UIPanel>();        if (m_targetPanel == null)            throw new ArgumentNullException("Cann't find the right UIPanel");        if (m_targetPanel.clipping != UIDrawCall.Clipping.SoftClip)            throw new InvalidOperationException("Don't need to clip");        m_shader = Shader.Find(ShaderName);        if (!IsInvoking("Clip"))            InvokeRepeating("Clip", 0, ClipInterval);    }    Vector4 CalcClipArea()    {        var clipRegion = m_targetPanel.finalClipRegion;        Vector4 nguiArea = new Vector4()        {            x = clipRegion.x - clipRegion.z / 2,            y = clipRegion.y - clipRegion.w / 2,            z = clipRegion.x + clipRegion.z / 2,            w = clipRegion.y + clipRegion.w / 2        };        var uiRoot = LuaUtils.UIRoot.GetComponent<UIRoot>();        var pos = m_targetPanel.transform.position - uiRoot.transform.position;        float h = 2;        float temp = h / uiRoot.manualHeight;        return new Vector4()        {            x = pos.x + nguiArea.x * temp,            y = pos.y + nguiArea.y * temp,            z = pos.x + nguiArea.z * temp,            w = pos.y + nguiArea.w * temp        };    }    void Clip()    {        Vector4 clipArea = CalcClipArea();        var particleSystems = this.GetComponentsInChildren<ParticleSystem>();        for (int i = 0; i < particleSystems.Length; i++)        {            var ps = particleSystems[i];            var mat = ps.renderer.material;            if (mat.shader.name != ShaderName)                mat.shader = m_shader;            mat.SetVector("_Area", clipArea);        }    }    void OnDestroy()    {        CancelInvoke("Clip");    }}
复制代码

 

对应的shader 代码如下:

复制代码
Shader "Bleach/Particles Additive Area Clip"{    Properties    {        _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)        _MainTex ("Particle Texture", 2D) = "white" {}        _Area ("Area", Vector) = (0,0,1,1)    }    Category    {        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }        Blend SrcAlpha One        AlphaTest Greater .01        ColorMask RGB        Cull Off        Lighting Off        ZWrite Off        Fog { Color (0,0,0,0) }                SubShader         {            Pass            {                CGPROGRAM                #pragma vertex vert                #pragma fragment frag                #pragma multi_compile_particles                #include "UnityCG.cginc"                sampler2D _MainTex;                fixed4 _TintColor;                float4 _Area;                                struct appdata_t                {                    float4 vertex : POSITION;                    fixed4 color : COLOR;                    float2 texcoord : TEXCOORD0;                };                struct v2f                {                    float4 vertex : SV_POSITION;                    fixed4 color : COLOR;                    float2 texcoord : TEXCOORD0;                    float2 worldPos : TEXCOORD1;                };                                float4 _MainTex_ST;                v2f vert (appdata_t v)                {                    v2f o;                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);                    o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);                    o.color = v.color;                    o.worldPos = mul(_Object2World, v.vertex).xy;                    return o;                }                fixed4 frag (v2f i) : SV_Target                {                    bool inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;                    return inArea? 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord) : fixed4(0,0,0,0);                }                ENDCG             }        }        }}
0 0
原创粉丝点击