Shader相关Mask裁切UI粒子特效或者3D模型
?
轉(zhuǎn)載自:http://www.xuanyusong.com/archives/3518
?
原理就是把Mask的裁切區(qū)域傳給粒子特效Shader,當(dāng)超出這個區(qū)域那么直接讓它完全透明即可。粒子特效的源生shader大家可以去unity官網(wǎng)下載,我在這里把需要修改的地方標(biāo)注給大家。
//add 注釋中的內(nèi)容就是我做修改的地方。
1 2 3 4 5 6 7 8 9 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 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的區(qū)域傳給shader。
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;//開發(fā)時分辨率寬
int designHeight = 640;//開發(fā)時分辨率高
float s1 = (float)designWidth / (float)designHeight;
float s2 = (float)width / (float)height;
//目標(biāo)分辨率小于 960X640的 需要計(jì)算縮放比例
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 是因?yàn)?/span>ugui默認(rèn)的縮放比例是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);
}
}
}
}
上面這段代碼寫的不太好,有一個更好的辦法來取Mask的裁切區(qū)域。
通過GetWorlCornets來確定裁切的區(qū)域
1 2 3 4 5 6 7 | ????????Vector3[] corners = new Vector3[4]; ????????RectTransform rectTransform = transform as RectTransform; ????????rectTransform.GetWorldCorners (corners); ????????minX = corners [0].x; ????????minY = corners [0].y; ????????maxX = corners [2].x; ????????maxY = corners [2].y; |
然后在把裁切的區(qū)域傳到shader中。
1 2 3 4 5 | ????????Material m = GetMaterial (renderer); ????????m.SetFloat("_MinX",minX); ????????m.SetFloat("_MinY",minY); ????????m.SetFloat("_MaxX",maxX); ????????m.SetFloat("_MaxY",maxY); |
為了做到不影響美術(shù),所以美術(shù)開發(fā)特效的時候還是用以前的shader。程序在運(yùn)行中對它進(jìn)行更換,這樣可以無縫進(jìn)行切換。
如果運(yùn)行時裁切區(qū)域發(fā)生變化, 可以重寫OnRectTransformDimensionsChange()方法來重新給材質(zhì)賦新的裁切區(qū)域
1 2 3 4 5 | ????protected override void OnRectTransformDimensionsChange () ????{ ????????base.OnRectTransformDimensionsChange (); ????????Change ();//重新再給材質(zhì)賦裁切參數(shù) ????} |
OK,如下圖所示,把粒子特效直接掛在Mask下面, 就可以進(jìn)行裁切了。。
在說一下3D模型, 理論上用上述的shader改一改就可以。 但是我還是建議3D模型用RenderTexture。比較好控制深度。
?
?
總結(jié)
以上是生活随笔為你收集整理的Shader相关Mask裁切UI粒子特效或者3D模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UGUI_使用DoTween
- 下一篇: 图集分配透明与不透明打包不到一起的错误