Unity3d之流光效果
所谓流光效果,如一个图片上一条刀光从左闪到右边,以下为实现代码:
c#代码:
using System; using UnityEngine; public class WalkLightEffect : MonoBehaviour { public Texture MainTex; public Texture LightTex; public float Duration; public float LightULen; public Vector2 Size; bool m_play; float m_timer; float m_t1; void Awake() { if (MainTex == null) throw new ArgumentNullException("MainTex"); if (LightTex == null) throw new ArgumentNullException("LightTex"); if (Duration <= 0) throw new ArgumentException("Duration"); if (LightULen <= 0 || LightULen >= 1) throw new ArgumentException("LightULen <= 0 || LightULen >= 1"); if (Size.x <= 0 || Size.y <= 0) throw new ArgumentException("Size.x <= 0 || Size.y <= 0"); GenerateRenderer(); m_t1 = (1 - LightULen) * Duration; } void GenerateRenderer() { // Mesh Mesh mesh = new Mesh(); mesh.vertices = new Vector3[4] { new Vector2(-Size.x/2,Size.y/2), new Vector2(Size.x/2,Size.y/2), new Vector2(-Size.x/2,-Size.y/2), new Vector2(Size.x/2,-Size.y/2), }; mesh.triangles = new int[6] { 0, 1, 2, 2, 1, 3 }; mesh.uv = new Vector2[4] { new Vector2(0,1), new Vector2(1,1), new Vector2(0,0), new Vector2(1,0), }; mesh.Optimize(); var mf = gameObject.AddComponent<MeshFilter>(); mf.mesh = mesh; // Material var mat = new Material(Shader.Find("Bleach/WalkLight")); mat.SetTexture("_MainTex", MainTex); mat.SetFloat("_LightLen", LightULen); var mr = gameObject.AddComponent<MeshRenderer>(); mr.sharedMaterial = mat; } void Update() { if (m_play) { renderer.material.SetFloat("_TimeRate", m_timer / Duration); m_timer += Time.deltaTime; if (m_timer > Duration) m_timer = 0; else if (m_timer > m_t1) renderer.material.SetFloat("_ReachBoundary", 1); else renderer.material.SetFloat("_ReachBoundary", -1); } } public bool Play { set { renderer.material.SetTexture("_LightTex", value ? LightTex : null); m_timer = 0; m_play = value; } } }
shader代码:
Shader "Bleach/WalkLight" { Properties { _MainTex ("Main", 2D) = "white" {} _LightTex("Light", 2D) = "black" {} _LightLen("Light Length", float) = 0 } SubShader { Pass { Tags { "RenderType"="Opaque" } LOD 200 Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag uniform sampler2D _MainTex; uniform sampler2D _LightTex; uniform fixed _LightLen; uniform fixed _ReachBoundary; // 小于0表示未到边界,大于0表示到达边界 uniform fixed _TimeRate; // 时间/周期 struct Data { fixed4 vertex:POSITION; fixed2 texcoord:TEXCOORD0; }; struct V2F { fixed4 pos:SV_POSITION; fixed2 uv:TEXCOORD0; }; V2F vert(Data v) { V2F o; o.pos=mul(UNITY_MATRIX_MVP,v.vertex); o.uv=v.texcoord; return o; } fixed4 frag(V2F i):COLOR { fixed4 main = tex2D(_MainTex,i.uv); fixed x = _ReachBoundary>0 && i.uv.x<_LightLen? i.uv.x+1 : i.uv.x; fixed lightU = (x - _TimeRate)/_LightLen; // u=(x-timer/Duration)/_LightLen; fixed4 light = tex2D(_LightTex,float2(lightU,i.uv.y)); return lerp(main,light,light.a); } ENDCG } } FallBack "Diffuse" }