unity简单示例——UI粒子裁切(shader+C#)

本文介绍了一种使用Unity3D实现UI遮罩的方法,通过编写C#脚本和Shader来限定粒子系统的显示区域。具体包括:创建自定义UI组件UISuperMask,通过获取世界坐标来更新遮罩范围,并在Shader中对粒子系统的透明度进行裁剪。

先看一下效果
UI粒子裁切
C#脚本

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

[DisallowMultipleComponent]
[RequireComponent(typeof(Image))]
[AddComponentMenu("UI/UISuperMask")]
public class UISuperMask :Mask 
{
	private float m_LastminX=-1f,m_LastminY=-1f,m_LastmaxX=-1f,m_LastmaxY=-1f;
	private float m_MinX=0f,m_MinY=0f,m_MaxX=0f,m_MaxY=0f;
	private Vector3[] m_Corners = new Vector3[4]; 
	private Image m_Image;

	void GetWorldCorners()
	{
		if(!Mathf.Approximately(m_LastminX,m_MinX) ||
			!Mathf.Approximately(m_LastminY,m_MinY)||
			!Mathf.Approximately(m_LastmaxX,m_MaxX)||
			!Mathf.Approximately(m_LastmaxY,m_MaxY))
		{
			RectTransform rectTransform = transform as RectTransform;
			rectTransform.GetWorldCorners (m_Corners);

			m_LastminX = m_MinX;
			m_LastminY = m_MinY;
			m_LastmaxX = m_MaxX;
			m_LastmaxY = m_MaxY;


			m_MinX = m_Corners [0].x;
			m_MinY = m_Corners [0].y;
			m_MaxX = m_Corners [2].x;
			m_MaxY = m_Corners [2].y;
            Debug.LogFormat("MinX:{0},MaxX:{1},MinY:{2},MaxY:{3}",m_MinX,m_MaxX,m_MinY,m_MaxY);
		}
	}

	protected override void OnRectTransformDimensionsChange ()
	{
		base.OnRectTransformDimensionsChange ();
		Refresh ();
	}

	public void Refresh()
	{
		GetWorldCorners ();
		if(Application.isPlaying)
		{
			foreach( ParticleSystemRenderer system in  transform.GetComponentsInChildren<ParticleSystemRenderer>(true))
			{
				SetRenderer(system);
			}
		}
	}


	void SetRenderer(Renderer renderer)
	{
		if (renderer.sharedMaterial) {
			Shader shader = Resources.Load<Shader> ("Alpha Blended Premultiply");
			renderer.material.shader = shader;
			Material m = renderer.material;
			m.SetFloat("_MinX",m_MinX);
			m.SetFloat("_MinY",m_MinY);
			m.SetFloat("_MaxX",m_MaxX);
			m.SetFloat("_MaxY",m_MaxY);
		}
	}

}

Shader脚本

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "UI/Mask/Particles/Alpha Blended Premultiply" {
Properties {
	_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 One OneMinusSrcAlpha 
	ColorMask RGB
	Cull Off Lighting Off ZWrite Off

	SubShader {
		Pass {
		
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_particles

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			fixed4 _TintColor;
			
			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;
            //-------------------add----------------------
            float _MinX;
            float _MaxX;
            float _MinY;
            float _MaxY;
            //-------------------add----------------------
			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				#ifdef SOFTPARTICLES_ON
				o.projPos = ComputeScreenPos (o.vertex);
				COMPUTE_EYEDEPTH(o.projPos.z);
				#endif
                //-------------------add----------------------
                o.vpos = v.vertex.xyz;
                //-------------------add----------------------
				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
				
				fixed4 col =  i.color * tex2D(_MainTex, i.texcoord) * i.color.a;
				//-------------------add----------------------
                col.a *= (i.vpos.x >= _MinX );
                col.a *= (i.vpos.x <= _MaxX);
                col.a *= (i.vpos.y >= _MinY);
                col.a *= (i.vpos.y <= _MaxY);
                col.rgb *= col.a;
                //-------------------add----------------------
                return col;
			}
			ENDCG 
		}
	}
}
}

本篇内容主要引自雨松的unity3d游戏开发,,在此记录一下

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值