NGUI具有流光效果的UISprite

之前做过一个流光效果(http://www.cnblogs.com/jietian331/p/4748644.html)。

现将其改进一下,与NGUI结合起来,提供一个具有流光效果的组件:UIWalkLightSprite。

效果如图:

 

首先是此组件的源码,如下:

  1 using System;
  2 using UnityEngine;
  3 
  4 /// <summary>
  5 /// 具有流光效果的 UISprite。
  6 /// 注意:
  7 /// 1. 流光图片需命名为"Special_WalkLight"(待改善)
  8 /// 2. 流光的 UISprite 暂不支持 UIPanel 剪裁(待改善)
  9 /// 3. 设置 UISprite 的 color 将无效
 10 /// </summary>
 11 public class UIWalkLightSprite : UISprite
 12 {
 13     const string WalkLightShaderName = "Bleach/Walk Light Colored";
 14 
 15     float m_duration = 2f;
 16     float m_widthLight2Sprite;
 17     float m_timer;
 18     float m_t1;
 19     bool m_initedMat = true;
 20     Vector2 m_lightURange;
 21 
 22     void Awake()
 23     {
 24         // replace shader
 25         if (base.atlas.spriteMaterial.shader.name != WalkLightShaderName)
 26         {
 27             string tempAtlasName = string.Format("[WalkLightTempAtlas_{0}]", atlas.name);
 28             Transform t = transform.Find(tempAtlasName);
 29             if (t == null)
 30                 t = ((GameObject)GameObject.Instantiate(atlas.gameObject)).transform;
 31 
 32             t.gameObject.SetActive(false);
 33             t.name = tempAtlasName;
 34             t.parent = transform;
 35 
 36             var tempAtlas = t.GetComponent<UIAtlas>();
 37             if (tempAtlas.spriteMaterial.name != WalkLightShaderName)
 38             {
 39                 Material mat = (Material)GameObject.Instantiate(atlas.spriteMaterial);
 40                 mat.shader = Shader.Find(WalkLightShaderName);
 41                 tempAtlas.spriteMaterial = mat;
 42             }
 43 
 44             base.atlas = tempAtlas;
 45         }
 46     }
 47 
 48     public override void OnFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
 49     {
 50         base.OnFill(verts, uvs, cols);
 51 
 52         // set uv2 to vertex
 53         var lightSprite = atlas.GetSprite("Special_WalkLight");
 54         Rect lightOuter = new Rect(lightSprite.x, lightSprite.y, lightSprite.width, lightSprite.height);
 55         lightOuter = NGUIMath.ConvertToTexCoords(lightOuter, mainTexture.width, mainTexture.height);
 56 
 57         // 用 color 把流光图片的 uv 地址传到 shader 中,故会导致设置 color 无效
 58         cols.Clear();
 59         cols.Add(new Color(lightOuter.xMin, lightOuter.yMin, 0));
 60         cols.Add(new Color(lightOuter.xMin, lightOuter.yMax, 0));
 61         cols.Add(new Color(lightOuter.xMax, lightOuter.yMax, 0));
 62         cols.Add(new Color(lightOuter.xMax, lightOuter.yMin, 0));
 63 
 64         // data set to shader
 65         m_initedMat = false;
 66         m_lightURange = new Vector2(lightOuter.xMin, lightOuter.xMax);
 67 
 68         Rect spriteOuter = new Rect(mSprite.x, mSprite.y, mSprite.width, mSprite.height);
 69         spriteOuter = NGUIMath.ConvertToTexCoords(spriteOuter, mainTexture.width, mainTexture.height);
 70         m_widthLight2Sprite = (lightOuter.width * spriteOuter.height) / (lightOuter.height * spriteOuter.width);
 71         m_t1 = (1 - m_widthLight2Sprite) * m_duration;
 72     }
 73 
 74     protected override void OnUpdate()
 75     {
 76         base.OnUpdate();
 77 
 78         if (RendererMat != null)
 79         {
 80             if (!m_initedMat)
 81             {
 82                 m_initedMat = true;
 83 
 84                 // init
 85                 RendererMat.SetFloat("_LightWidthToMain", m_widthLight2Sprite);
 86                 RendererMat.SetVector("_LightURange", m_lightURange);
 87             }
 88 
 89             // 驱动流光动画
 90             RendererMat.SetFloat("_TimeRate", m_timer / m_duration);
 91 
 92             m_timer += Time.deltaTime;
 93 
 94             if (m_timer > m_duration)
 95                 m_timer = 0;
 96             else if (m_timer > m_t1)
 97                 RendererMat.SetFloat("_ReachBoundary", 1);
 98             else
 99                 RendererMat.SetFloat("_ReachBoundary", -1);
100         }
101     }
102 
103     Material RendererMat
104     {
105         get { return base.Renderer != null ? base.Renderer.sharedMaterial : null; }
106     }
107 
108     public float Duration
109     {
110         set
111         {
112             if (value <= 0)
113                 throw new ArgumentException("value <= 0");
114 
115             m_duration = value;
116             m_t1 = (1 - m_widthLight2Sprite) * m_duration;
117         }
118     }
119 }
UISprite

 

对应的 shader 如下:

  1 Shader "Bleach/Walk Light Colored"
  2 {
  3     Properties
  4     {
  5         _MainTex ("RGB", 2D) = "black" {}
  6         _AlphaTex ("Alpha", 2D) = "black" {}
  7     }
  8     
  9     SubShader
 10     {
 11         LOD 200
 12 
 13         Tags
 14         {
 15             "Queue" = "Transparent"
 16             "IgnoreProjector" = "True"
 17             "RenderType" = "Transparent"
 18         }
 19         
 20         Pass
 21         {
 22             Cull Off
 23             Lighting Off
 24             ZWrite Off
 25             Fog { Mode Off }
 26             Offset -1, -1
 27             Blend SrcAlpha OneMinusSrcAlpha
 28 
 29             CGPROGRAM
 30             #pragma vertex vert
 31             #pragma fragment frag            
 32 
 33             sampler2D _MainTex;
 34             sampler2D _AlphaTex;
 35 
 36             uniform fixed2 _LightURange;                // 光图片在 u 上的范围
 37             uniform fixed _LightWidthToMain;            // 光图片宽度占主图片宽度的比例
 38             uniform fixed _ReachBoundary;                // 小于0表示未到边界,大于0表示到达边界
 39             uniform fixed _TimeRate;                    // 时间/周期
 40     
 41             struct appdata_t
 42             {
 43                 float4 vertex : POSITION;
 44                 float2 texcoord : TEXCOORD0;
 45                 fixed4 color : COLOR;
 46             };
 47     
 48             struct v2f
 49             {
 50                 float4 vertex : SV_POSITION;
 51                 half2 texcoord : TEXCOORD0;
 52                 half2 uv2 : TEXCOORD1;        // 流光图的 uv 坐标
 53             };
 54     
 55             v2f vert (appdata_t v)
 56             {
 57                 v2f o;
 58                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
 59                 o.texcoord = v.texcoord;
 60                 fixed fixedU=(v.color.x - _LightURange.x) / (_LightURange.y - _LightURange.x);        // 把 u 坐标转到[0,1]范围
 61                 o.uv2 = fixed2(fixedU,v.color.y);
 62                 return o;
 63             }
 64                 
 65             fixed4 frag (v2f IN) : COLOR
 66             {
 67                 fixed4 main;
 68                 main.rgb = tex2D(_MainTex, IN.texcoord).rgb;
 69                 main.a = tex2D(_AlphaTex, IN.texcoord).a;
 70                 
 71                 // 流光
 72                 fixed x = _ReachBoundary > 0 && IN.uv2.x < _LightWidthToMain ? IN.uv2.x+1 : IN.uv2.x;
 73                 fixed lightU = (x - _TimeRate) / _LightWidthToMain;
 74                 lightU = (_LightURange.y - _LightURange.x) * lightU + _LightURange.x;                // 把 u 坐标从[0,1]范围转回来
 75                 lightU = clamp(lightU, _LightURange.x, _LightURange.y);
 76                 fixed2 lightUV = fixed2(lightU, IN.uv2.y);
 77                 fixed lightA = tex2D(_AlphaTex, lightUV).a;
 78 
 79                 // 融合
 80                 fixed3 col = main.rgb * (1 + lightA * 1.5);
 81                 return fixed4(col, main.a);
 82             }
 83             ENDCG
 84         }
 85     }
 86 
 87     SubShader
 88     {
 89         LOD 100
 90 
 91         Tags
 92         {
 93             "Queue" = "Transparent"
 94             "IgnoreProjector" = "True"
 95             "RenderType" = "Transparent"
 96         }
 97         
 98         Pass
 99         {
100             Cull Off
101             Lighting Off
102             ZWrite Off
103             Fog { Mode Off }
104             Offset -1, -1
105             ColorMask RGB
106             Blend SrcAlpha OneMinusSrcAlpha
107             ColorMaterial AmbientAndDiffuse
108             
109             SetTexture [_MainTex]
110             {
111                 Combine Texture * Primary
112             }
113 
114             SetTexture [_AlphaTex] 
115             {
116                 Combine previous, texture * primary 
117             }
118         }
119     }
120 }
Shader

 

转载请注明出处:http://www.cnblogs.com/jietian331/p/5261772.html

posted @ 2016-03-10 14:28  孤独の巡礼  阅读(2523)  评论(0编辑  收藏  举报