zoukankan      html  css  js  c++  java
  • Unity NGUI UIPanel下对粒子的剪裁

    转:http://www.cnblogs.com/jietian331/p/5075487.html

    使用 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 
                }
            }    
        }
    }
  • 相关阅读:
    Python解释器安装
    有钱就放余额宝的人,这个习惯恐怕要改一改!
    这么详细的存储基础知识,你不看看? 会后悔的!
    超全!华为交换机端口vlan详解~
    华为:鸿蒙绝不是安卓换皮!!!
    VS Code 真的会一统江湖吗?
    用户与安全 -(1)Linux用户及组管理
    运维必看!这个技能薪水28.8万,工资竟然还只是零花钱....
    原来 Linux 日志文件系统是这样工作的~
    干货长文:Linux 文件系统与持久性内存介绍
  • 原文地址:https://www.cnblogs.com/Yellow0-0River/p/8310363.html
Copyright © 2011-2022 走看看