码迷,mamicode.com
首页 > 编程语言 > 详细

[Unity] Simple Shaderlab 1 // UI用的简单shader 1 - 流光

时间:2015-11-13 20:48:04      阅读:725      评论:0      收藏:0      [点我收藏+]

标签:

最近经常要给2D游戏写一些新的shader来做特效。比起粒子特效,着色器特效可能更适合UI和2D元素上的表现。

先看一下效果:

技术分享

 

关于在shaderlab种实现流光的文章很多,但很少有给UI实现的,并且常常只是Add一层颜色,并没有去表现“光”的效果。

以下是shader全文,后面会介绍一些细节:

  1 Shader "UI/Unlit/Flowlight"
  2 {
  3     Properties
  4     {
  5         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
  6         _Color ("Tint", Color) = (1, 1, 1, 1)
  7         [MaterialToggle] PixelSnap ("Pixel snap", float) = 0
  8         
  9         /* Flowlight */
 10         _FlowlightTex ("Add Move Texture", 2D) = "white" {}
 11         _FlowlightColor ("Flowlight Color", Color) = (0, 0, 0, 1)
 12         _Power ("Power", float) = 1
 13         _SpeedX ("SpeedX", float) = 1
 14         _SpeedY ("SpeedY", float) = 0
 15         /* --------- */
 16 
 17         /* UI */
 18         _StencilComp ("Stencil Comparison", Float) = 8
 19         _Stencil ("Stencil ID", Float) = 0
 20         _StencilOp ("Stencil Operation", Float) = 0
 21         _StencilWriteMask ("Stencil Write Mask", Float) = 255
 22         _StencilReadMask ("Stencil Read Mask", Float) = 255
 23         /* -- */
 24     }
 25 
 26     SubShader
 27     {
 28         Tags
 29         { 
 30             "Queue"="Transparent" 
 31             "IgnoreProjector"="True" 
 32             "RenderType"="Transparent" 
 33             "PreviewType"="Plane"
 34             "CanUseSpriteAtlas"="True"
 35         }
 36 
 37         Cull Off
 38         Lighting Off
 39         ZWrite Off
 40         Blend One OneMinusSrcAlpha
 41         
 42         /* UI */
 43         Stencil
 44         {
 45             Ref [_Stencil]
 46             Comp [_StencilComp]
 47             Pass [_StencilOp] 
 48             ReadMask [_StencilReadMask]
 49             WriteMask [_StencilWriteMask]
 50         }
 51         /* -- */
 52 
 53         Pass
 54         {
 55         CGPROGRAM        
 56             #pragma vertex vert
 57             #pragma fragment frag
 58             #pragma multi_compile _ PIXELSNAP_ON
 59             #include "UnityCG.cginc"
 60             
 61             struct appdata_t
 62             {
 63                 float4 vertex : POSITION;
 64                 float4 color : COLOR;
 65                 float2 texcoord : TEXCOORD0;
 66             };
 67 
 68             struct v2f
 69             {
 70                 float4 vertex : SV_POSITION;
 71                 fixed4 color : COLOR;
 72                 half2 texcoord : TEXCOORD0;
 73 
 74                 /* Flowlight */
 75                 half2 texflowlight : TEXCOORD1;
 76                 /* --------- */
 77             };
 78             
 79             fixed4 _Color;
 80 
 81             /* Flowlight */
 82             fixed4 _FlowlightColor;
 83             float _Power;
 84             sampler2D _FlowlightTex;
 85             fixed4 _FlowlightTex_ST;
 86             fixed _SpeedX;
 87             fixed _SpeedY;
 88             /* --------- */
 89 
 90             v2f vert(appdata_t IN)
 91             {
 92                 v2f OUT;
 93                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
 94                 OUT.texcoord = IN.texcoord;
 95 
 96                 /* Flowlight */
 97                 OUT.texflowlight = TRANSFORM_TEX(IN.texcoord, _FlowlightTex);
 98                 OUT.texflowlight.x += _Time * _SpeedX;
 99                 OUT.texflowlight.y += _Time * _SpeedY;
100                 /* --------- */
101 
102                 OUT.color = IN.color * _Color;
103                 #ifdef PIXELSNAP_ON
104                 OUT.vertex = UnityPixelSnap (OUT.vertex);
105                 #endif
106 
107                 return OUT;
108             }
109 
110             sampler2D _MainTex;
111 
112             fixed4 frag(v2f IN) : SV_Target
113             {
114                 fixed4 c = tex2D(_MainTex, IN.texcoord);
115 
116                 /* Flowlight */
117                 fixed4 cadd = tex2D(_FlowlightTex, IN.texflowlight) * _Power;
118                 cadd.rgb *= c.rgb;
119                 c.rgb += cadd.rgb;
120                 c.rgb *= c.a;
121                 /* --------- */
122 
123                 return c;
124             }
125         ENDCG
126         }
127     }
128 }

其实博文发出来之后这个改过一次,因为是用的Sprite-Default改的,能用在UI上但没有实现遮罩等等功能,这次补上。

/* UI */里的就是添加上的属于UI shader的部分,如果只是用在Sprite上的话这部分可以删掉。

而/* Flowlight */里的是从Sprite-Default基础上添加的部分,去掉之后就变成Sprite-Default原文了(

 

其实流程和正常的UV滚动叠加没有什么区别,注意要用UI传入的UV计算纹理坐标。

97  OUT.texflow = TRANSFORM_TEX(IN.texcoord, _FlowlightTex);

之后两张纹理在frag中叠加输出,需要注意的只有一行:

118  cadd.rgb *= c.rgb;

很多shader作者在写流光的时候只是把叠加纹理的颜色+=在了主纹理上,但如果先将叠加纹理乘以主纹理的颜色,就会让暗色变得更暗,更符合光吸收的感觉,再配合Power控制光强度可以更好地表现光。

当然这样一来的副作用就是流光纹理本身的颜色就没有用了,因为变成了只用灰度,毕竟本来目的只是在打光。需要颜色的话可以在这行的下一行乘以自定义颜色,这里就不写了。

以上是需要留意的部分。

 

具体流程上,在vert中先获得流光纹理的纹理坐标OUT.texflow,而后使用_Time时间参数让纹理坐标随时间偏移,注意偏移操作在顶点着色vert部分进行而不是在片段着色frag,这样不会浪费计算量。

之后在frag中进行叠加将流光纹理与主纹理叠加,注意是c.rgb += cadd.rgb,否则c += cadd会导致透明通道也被叠加上去,对下一步c的预乘透明通道产生影响。

 

在纹理的制作上,因为是循环滚动,所以为了不会让光出现过度频繁,需要在流光纹理的旁边加上合适宽度的黑色区域。

下面是本文开头动图使用的流光纹理:

 技术分享

它在光线纹理(正方形)的左侧加上了等宽的黑色区域,让纹理变为了2x1的宽高,这样再将材质的Tiling改为X:0.5 Y:1就可以让光出现的频率减半了,当然还可以把光线区域在PS再缩小为66%,这样就可以让光线的出现频率变为最初的1/3了(别忘了改Tilling),其他频率以此类推。

 

下一次会分享一下uGui用的溶解。说是uGui用,其实使用了UI或Sprite Shader的东西都可以用。

[Unity] Simple Shaderlab 1 // UI用的简单shader 1 - 流光

标签:

原文地址:http://www.cnblogs.com/twelveh/p/4963031.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!