您的位置:首页 > 移动开发 > Unity3D

Unity NGUI SoftPanel 裁剪粒子或者模型

2018-01-20 10:09 796 查看
NGUI本身的裁剪有例子,在自带的Shader中的Transparent Colored 1

v2f vert(appdata_t v)

{
 v2f o;
 o.vertex = UnityObjectToClipPos(v.vertex);
 o.color = v.color;
 o.texcoord = v.texcoord;

 //就是这句 传进来相对于drawcall里设置的自身坐标 NGUI通过处理 近似于屏幕坐标 然后通过裁剪区域运算
 o.worldPos = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;
 return o;

}

但是粒子或者模型不在NGUI的drawcall中,因此无法通过复制他的逻辑实现裁剪,可以根据这个思路写一个,其实原理就是给shader设置一个裁剪区域。

//这是示例shader 重点其实就注释的4个地方 使用Unity版本5.6.5f1

Shader "Effect/Effect_additive_LV1" {

    Properties {

        _MainTex ("Base (RGB)", 2D) = "white" {}

        _tintColor("Tint Color",Color) = (0.5,0.5,0.5,1)

    }

    SubShader {

        Tags { "Queue" = "Transparent+100" "RenderType"="Transparent" "Ignoreprojector" = "True"}

        LOD 200

        lighting off

        zwrite off

        Blend SrcAlpha one

        cull off

        fog{mode off}

        ColorMask RGB

        pass{

        CGPROGRAM

        #pragma vertex vert

        #pragma fragment frag

        #include "UnityCG.cginc"

        

        sampler2D _MainTex;

        float4 _MainTex_ST;

        float4 _tintColor;

 //1. 先设置一个裁剪区域 左下和右上 2个坐标xy坐标 用一个float4即可代表

        float4 _ClipRange0 = float4(-1, -1, 1, 1);

        struct v2f {

            float4 pos : SV_POSITION;

            float2 uv : TEXCOORD0;

            float4 color : Color;

  //2. 设置一个顶点转换到屏幕的2d坐标系的坐标
  float2
viewPos : TEXCOORD1;

        };

 struct appdata_t

  {
  float4
vertex : POSITION;
  fixed4
color : COLOR;
  float2
texcoord : TEXCOORD0;
 };        

        v2f vert (appdata_t v) 

        {

              v2f o;

              o.pos = UnityObjectToClipPos (v.vertex);

              o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

              o.color = v.color;

  //3. 通过自带函数转换成屏幕坐标 viewPos范围是-1至1,左下是(-1,
-1) 右上是(1, 1)

  o.viewPos
= UnityObjectToViewPos (v.vertex);

              return o;

        }

        

        

        fixed4 frag(v2f i) : color 

        {
  fixed4
col = tex2D(_MainTex, i.uv) * 2 * i.color * _tintColor; 

  //4. 判断是否在裁剪区域外 如果在裁剪区域外就裁掉
  col.a
*= i.viewPos.x <= _ClipRange0.x || i.viewPos.y <= _ClipRange0.y || i.viewPos.x >= _ClipRange0.z || i.viewPos.y >= _ClipRange0.w ? 0:1;

           
 return col;

        }

        

        ENDCG

        }

    }

    FallBack "Diffuse"

}

然后还要通过脚本传递裁剪区域,写的比较简单,大家可以自行扩展

//如果父物体的第一个panel是softpanel裁剪 则裁剪粒子

    public void SetParticleClip()

    {

        if (UICamera.mainCamera != null)

        {

            UIPanel panel = GetComponentInParent<UIPanel>();

            if (panel != null)

            {

                if (panel.clipping == UIDrawCall.Clipping.SoftClip)

                {

                    Vector3 bottomLeft = UICamera.mainCamera.WorldToViewportPoint(panel.worldCorners[0]);

                    Vector3 topRight = UICamera.mainCamera.WorldToViewportPoint(panel.worldCorners[2]);

  //WorldToViewportPoint这个函数转换完的范围是0至1,左下是(0,
0) 右上是(1, 1)

                Vector4 temp = new Vector4(bottomLeft.x * 2 - 1, bottomLeft.y * 2 - 1, topRight.x * 2 - 1, topRight.y * 2 - 1);

                 int propertyInt = Shader.PropertyToID("_ClipRange0");

                    ParticleSystem[] particles = GetComponentsInChildren<ParticleSystem>();

                    if (particles != null)

                    {

                        for (int i = 0; i < particles.Length; i++)

                        {

                            Renderer render = particles[i].GetComponent<Renderer>();

                            if (render != null)

                            {

                                if (render.material != null)

                                {

                                    render.material.SetVector(propertyInt, temp);

                                }

                            }

                        }

                    }

                }

            }

        }

    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息