Mask裁切UI粒子特效或者3D模型

Mask裁切UI粒子特效或者3D模型

刚好前几天有人问我这个问题,再加上新项目也可能用,所以这两天就研究了一下。其实如果粒子特效 和3D模型 都用RenderTexture来做的话就不会有裁切的问题,但是粒子特效用RenderTexture来做会有显示的问题,所以还是得用摄像机。废话不多说了,进入正题。

原理就是把Mask的裁切区域传给粒子特效Shader,当超出这个区域那么直接让它完全透明即可。粒子特效的源生shader大家可以去unity官网下载,我在这里把需要修改的地方标注给大家。

//add 注释中的内容就是我做修改的地方。

[C#] 纯文本查看 复制代码
 
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
Shader "Particles/Additive" {
Properties {
    _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    _MainTex ("Particle Texture", 2D) = "white" {}
    _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
     
    //-------------------add----------------------
      _MinX ("Min X", Float) = -10
      _MaxX ("Max X", Float) = 10
      _MinY ("Min Y", Float) = -10
      _MaxY ("Max Y", Float) = 10
      //-------------------add----------------------
     
}
  
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;
            //-------------------add----------------------
            float _MinX;
            float _MaxX;
            float _MinY;
            float _MaxY;
            //-------------------add----------------------
             
            struct appdata_t {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };
  
            struct v2f {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                #ifdef SOFTPARTICLES_ON
                float4 projPos : TEXCOORD1;
                #endif
                //-------------------add----------------------
                float3 vpos : TEXCOORD2;
                //-------------------add----------------------
            };
             
            float4 _MainTex_ST;
  
            v2f vert (appdata_t v)
            {
                v2f o;
                //-------------------add----------------------
                o.vpos = v.vertex.xyz;
                //-------------------add----------------------
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                #ifdef SOFTPARTICLES_ON
                o.projPos = ComputeScreenPos (o.vertex);
                COMPUTE_EYEDEPTH(o.projPos.z);
                #endif
                o.color = v.color;
                o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }
  
            sampler2D_float _CameraDepthTexture;
            float _InvFade;
             
            fixed4 frag (v2f i) : SV_Target
            {
                #ifdef SOFTPARTICLES_ON
                float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                float partZ = i.projPos.z;
                float fade = saturate (_InvFade * (sceneZ-partZ));
                i.color.a *= fade;
                #endif
                 
                //-------------------add----------------------
                 fixed4 c =2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
                 c.a *= (i.vpos.x >= _MinX );
                 c.a *= (i.vpos.x <= _MaxX);
                 c.a *= (i.vpos.y >= _MinY);
                 c.a *= (i.vpos.y <= _MaxY);
                 c.rgb *= c.a;
                return c;
                //-------------------add----------------------
            }
            ENDCG
        }
    }  
}
}


然后是自己写了个类继承Mask。把Mask的区域传给shader。

[C#] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
  
public class MyMask :Mask
{
    protected override void Start ()
    {
        base.Start ();
  
        int width = Screen.width;
        int height = Screen.height;
        int designWidth = 960;//开发时分辨率宽
        int designHeight = 640;//开发时分辨率高
        float s1 = (float)designWidth / (float)designHeight;
        float s2 = (float)width / (float)height;
  
        //目标分辨率小于 960X640的 需要计算缩放比例
        float contentScale =1f;
         if(s1 > s2) {
            contentScale = s1/s2;
        }
        Canvas  canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
        Vector2 pos;
        if(RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, transform.position, canvas.camera, out pos)){
            ParticleSystem  [] particlesSystems  = transform.GetComponentsInChildren<ParticleSystem>();
            RectTransform rectTransform = transform as RectTransform;
            float minX,minY,maxX,maxY;
            minX = rectTransform.rect.x  + pos.x;
            minY = rectTransform.rect.y+ pos.y;
            maxX = minX + rectTransform.rect.width ;
            maxY = minY + rectTransform.rect.height;
  
  
            //这里 100  是因为ugui默认的缩放比例是100  你也可以去改这个值,但是我觉得最好别改。
            foreach(ParticleSystem particleSystem in particlesSystems)
            {
                particleSystem.renderer.sharedMaterial.SetFloat("_MinX",minX/100/contentScale);
                particleSystem.renderer.sharedMaterial.SetFloat("_MinY",minY/100/contentScale);
                particleSystem.renderer.sharedMaterial.SetFloat("_MaxX",maxX/100/contentScale);
                particleSystem.renderer.sharedMaterial.SetFloat("_MaxY",maxY/100/contentScale);
            }
        }
    }
}


OK,如下图所示,把粒子特效直接挂在Mask下面, 就可以进行裁切了。。

Mask裁切UI粒子特效或者3D模型

1.png (181.88 KB, 下载次数: 0)

下载附件  保存到相册

2015-7-8 17:50 上传