• 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

  • 相关阅读:
    堆排序实现
    Unable to convert MySQL date/time value to System.DateTime
    想想那些除了技术之外重要的事情
    js小功能
    01输入框回车触发操作
    javascript闭包
    BQ27510 电量计的校准 的 C语言实现
    嵌入式Linux开发教程:Linux常见命令(上篇)
    技术团队的情绪与效率
    如何有效使用Project(2)——进度计划的执行与监控
  • 原文地址:https://www.cnblogs.com/jietian331/p/5261772.html
Copyright © 2020-2023  润新知