当前位置:   article > 正文

Unity Shader 效果(1) :图片流光效果

unity 流光shader

很多游戏Logo中可以看到这种流光效果,一般的实现方案就是对带有光条的图片uv根据时间进行移动,然后和原图就行叠加实现,不过实现过程中稍稍有点需要注意的地方。之前考虑过风宇冲的实现方式,但是考虑到shader中太多的计算,还是放弃了。
mark

基础版本
  1. Shader "UICustom/ImageFlashEffect2"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Main Texture", 2D) = "white" {}
  6. _LightTex ("Light Texture", 2D) = "white" {}
  7. _LightColor("Light Color",Color) = (1,1,1,1)
  8. _LightPower("Light Power",Range(0,5)) = 1
  9. //每次持续时间,受Angle和Scale影响
  10. _LightDuration("Light Duration",Range(0,10)) = 1
  11. //时间间隔,受Angle和Scale影响
  12. _LightInterval("Light Interval",Range(0,20)) = 3
  13. }
  14. SubShader
  15. {
  16. Tags
  17. {
  18. "Queue"="Transparent"
  19. "IgnoreProjector"="True"
  20. "RenderType"="Transparent"
  21. }
  22. Cull Off
  23. Lighting Off
  24. ZWrite Off
  25. Fog { Mode Off }
  26. Offset -1, -1
  27. Blend SrcAlpha OneMinusSrcAlpha
  28. AlphaTest Greater 0.1
  29. Pass
  30. {
  31. CGPROGRAM
  32. #pragma vertex vert
  33. #pragma fragment frag
  34. #include "UnityCG.cginc"
  35. struct appdata
  36. {
  37. float4 vertex : POSITION;
  38. float2 uv : TEXCOORD0;
  39. };
  40. struct v2f
  41. {
  42. float2 uv : TEXCOORD0;
  43. float4 vertex : SV_POSITION;
  44. float2 lightuv : TEXCOORD1;
  45. };
  46. sampler2D _MainTex;
  47. float4 _MainTex_ST;
  48. sampler2D _LightTex ;
  49. float4 _LightTex_ST;
  50. half _LightInterval ;
  51. half _LightDuration ;
  52. half4 _LightColor ;
  53. half _LightPower ;
  54. half _LightOffSetX ;
  55. half _LightOffSetY ;
  56. v2f vert (appdata v)
  57. {
  58. v2f o;
  59. o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
  60. fixed currentTimePassed = fmod(_Time.y,_LightInterval);
  61. //uv offset, Sprite wrap mode need "Clamp"
  62. fixed offsetX = currentTimePassed / _LightDuration;
  63. fixed offsetY = currentTimePassed / _LightDuration;
  64. fixed2 offset ;
  65. offset.x = offsetX - 0.5f;
  66. offset.y = offsetY - 0.5f;
  67. o.lightuv = v.uv + offset ;
  68. o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  69. o.lightuv = TRANSFORM_TEX(o.lightuv, _LightTex);
  70. return o;
  71. }
  72. fixed4 frag (v2f i) : SV_Target
  73. {
  74. fixed4 mainCol = tex2D(_MainTex, i.uv);
  75. fixed4 lightCol = tex2D(_LightTex, i.lightuv);
  76. lightCol *= _LightColor ;
  77. //need blend
  78. //lightCol.rgb *= mainCol.rgb ;
  79. fixed4 fininalCol ;
  80. fininalCol.rgb = mainCol.rgb + lightCol.rgb * _LightPower;
  81. fininalCol.a = mainCol.a * lightCol.a ;
  82. return fininalCol ;
  83. }
  84. ENDCG
  85. }
  86. }
  87. }

需要注意的点:

  1. 时间间隔问题
  1. fixed currentTimePassed = fmod(_Time.y,_LightInterval);
  2. //uv offset, Sprite wrap mode need "Clamp"
  3. fixed offsetX = currentTimePassed / _LightDuration;
  4. fixed offsetY = currentTimePassed / _LightDuration;

offsetX 、offsetY其实是0~_LightInterval的数值,需要设置图片为光线图片的Wrap模式为Clamp,才能实现时间间隔控制

  1. 色彩融合
    Pixel着色器中frag()函数是通过原始颜色和光线颜色叠加的方式实现的,也有将光线颜色和原图混合后再叠加的做法,这个我觉得看实际应用。注意alpha的控制
优化
1. 增加角度和大小控制

基本版本的实现中光线只能根据流光图片中亮线的宽度和方向决定实际的滚动方向和大小。有时候如果需要经常调节方向和大小,可以考虑加入相关因素。流光的Uv是通过原图当前Uv加上时间轴参数获得,可以考虑通过修改流光uv的计算方式来实现。如下面代码。不过这种方式增加了一定计算量,不需要的话则直接跳过。还有一点就是流光贴图必须是垂直或者水平。

  1. float2 base = v.uv ;
  2. base.x -= _LightOffSetX ;
  3. base.y -= _LightOffSetX ;
  4. base = base / _LightScale ;
  5. float2 base2 = v.uv;
  6. base2.x = base.x * cosInRad - base.y * sinInRad ;
  7. base2.y = base.y * cosInRad + base.x * sinInRad ;
  8. o.lightuv = base2 + offset ;
材质复用

只是想不同的图片都是使用相同的材质,应该保证每个图片的效果都可以独立进行修改保存,可以考虑每张图片都创建一份材质,然后修改其参数。

  1. void UpdateParam()
  2. {
  3. if (Material == null)
  4. {
  5. Debug.LogWarning("Metarial is miss");
  6. return;
  7. }
  8. if (mGraphic == null)
  9. {
  10. mGraphic = GetComponent<MaskableGraphic>();
  11. }
  12. if (mGraphic is Text)
  13. {
  14. Debug.LogError("FlashEffec need component type of Image、RawImage");
  15. return;
  16. }
  17. if (mDynaMaterial == null)
  18. {
  19. mDynaMaterial = new Material(Material);
  20. mDynaMaterial.name = mDynaMaterial.name + "(Copy)";
  21. mDynaMaterial.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
  22. }
  23. if (mDynaMaterial == null)
  24. {
  25. return;
  26. }
  27. mDynaMaterial.mainTexture = null;
  28. if (OverrideTexture != null)
  29. {
  30. mDynaMaterial.mainTexture = OverrideTexture;
  31. if (mGraphic is RawImage)
  32. {
  33. RawImage img = mGraphic as RawImage;
  34. img.texture = null;
  35. }
  36. else if (mGraphic is Image)
  37. {
  38. Image img = mGraphic as Image;
  39. img.sprite = null;
  40. }
  41. }
  42. else
  43. {
  44. mDynaMaterial.mainTexture = mGraphic.mainTexture;
  45. }
  46. if (Duration > Interval)
  47. {
  48. Debug.LogWarning("ImageFlashEffect.UpdateParam:Duration need less Interval");
  49. Interval = Duration + 0.5f;
  50. }
  51. mDynaMaterial.SetColor("_LightColor", Color);
  52. mDynaMaterial.SetFloat("_LightPower", Power);
  53. mDynaMaterial.SetFloat("_LightScale", Scale);
  54. mDynaMaterial.SetFloat("_LightAngle", Angle);
  55. mDynaMaterial.SetFloat("_LightDuration", Duration);
  56. mDynaMaterial.SetFloat("_LightInterval", Interval);
  57. mDynaMaterial.SetFloat("_LightOffSetX", OffSet);
  58. mGraphic.material = mDynaMaterial;
  59. mGraphic.SetMaterialDirty();
  60. }

下载:https://github.com/carlosCn/Unity_Image_Flash_Effect

参考

http://blog.csdn.net/qq992817263/article/details/51200424
http://qkxue.net/info/169189/Unity-Simple-Shaderlab-uGui-shader-1

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/109499?site
推荐阅读
相关标签
  

闽ICP备14008679号