【Unity Shader】基于UGUI的水波倒影按钮

来源:互联网 发布:node 压力测试工具 编辑:程序博客网 时间:2024/05/06 23:48

先上效果:


首先说一下原理,这个shader实现的原理很简单,通过使用两个Pass,第一个Pass先正常渲染一遍UI,第二个Pass将UV坐标y值上下翻转,并将顶点坐标偏移一定距离,再做扭曲操作。实现起来并不是很难,主要需要注意的就是UGUIshader要注意的几个格式,比如UGUI shader都要有模板测试和ColorMask的部分(如果你希望你的shader能支持UGUI mask的话)。


首先是shader的模板测试部分,(模板测试参考官网:http://docs.unity3d.com/Manual/SL-Stencil.html)


在属性块中定义这些属性,如果希望能支持UIMask,则这是必须的,注意前5段定义了模板缓存的比较函数,模板值,测试成功后的操作函数,以及模板读写的掩码,shader中的使用方式如下:


我们知道正常使用模板缓存,需要指定模板值,比较函数等,并且通常都是指定一个具体的枚举值,比如Greater,Less,Equal,LEqual等,而UGUIshader则直接将具体的数值传入,当然这一过程是有UGUIMask脚本完成的,那么这些具体的数值是如何和比较函数一一对应的,我们可以看下UnityEngine.Rendering名称空间,


其中包括一些shader中常用枚举,包括blend的混合因子,当然还有深度测试和模板测试的比较方式,cullMode等,也就是说如果希望尝试编写一个shader,其光栅化阶段的模板测试,深度测试,以及混合等是可以通过脚本控制的,则可以使用这种方式。

另外UGUIshader中还是用了ColorMask,注意UGUI源码中Mask类是如何使用ColorMask的,可以看到当UGUIMask关闭ShowMaskGraphic时colormask会被设为0,也就是UGUImask通过使用colormask来完成”是否显示mask本身“的功能。

以上部分是UGUIshader中为了让你写的UIshader支持Mask功能所做的事。

(支持Mask的UGUI水波:)


另外,UGUI有一点需要注意,UGUI Image类的颜色信息和Button类的鼠标滑过或点击的反馈颜色都是通过直接修改UGUI的网格的顶点色实现的,换句话说如果希望自己写的UGUIshader能获取到Button中鼠标滑过或点击的颜色,则必须在shader的顶点输入结构中包含顶点颜色信息。


接下来说一下水波的原理,主要就是使用一张噪波贴图,其R通道与G通道如下:


shader中通过读入该噪波贴图的RG通道,并将其颜色值转换为-1到1的范围,再乘上一个偏移强度,就得到了uv的偏移量,当使用_Time将噪波贴图运动,就能达到水波的效果了。另外我还在shader中加入了扭曲强度和alpha的淡入淡出效果,直接贴源码:

Shader "MyUI/UI Wave"{Properties{[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}_NoiseTex ("Wave Noise", 2D) = "white" {}//噪波贴图_Offset ("Vertex Offset", vector) = (0, 0, 0, 0)//表示顶点的偏移量_Indentity ("Indentity", float) = 0.1//表示水波的扭曲强度_SpeedX ("WaveSpeedX", float) = 0.08//噪波贴图延X方向的移动速度_SpeedY ("WaveSpeedY", float) = 0.04//噪波贴图延Y方向的移动速度_AlphaFadeIn ("AlphaFadeIn", float) = 0.0//水波的淡入位置_AlphaFadeOut ("AlphaFadeOut", float) = 1.0//水波的淡出位置_TwistFadeIn ("TwistFadeIn", float) = 1.0//扭曲的淡入位置_TwistFadeOut ("TwistFadeOut", float) = 1.01//扭曲的淡出位置_TwistFadeInIndentity ("TwistFadeInIndentity", float) = 1.0//扭曲的淡入强度_TwistFadeOutIndentity ("TwistFadeOutIndentity", float) = 1.0//扭曲的淡出强度_Color ("Tint", Color) = (1,1,1,1)_StencilComp ("Stencil Comparison", Float) = 8_Stencil ("Stencil ID", Float) = 0_StencilOp ("Stencil Operation", Float) = 0_StencilWriteMask ("Stencil Write Mask", Float) = 255_StencilReadMask ("Stencil Read Mask", Float) = 255_ColorMask ("Color Mask", Float) = 15}CGINCLUDE//定义顶点的输入结构struct appdata_ui{float4 vertex   : POSITION;float4 color    : COLOR;float2 texcoord : TEXCOORD0;};//定义顶点到片段的结构struct v2f_ui{float4 pos   : SV_POSITION;fixed4 color    : COLOR;half2 uv  : TEXCOORD0;};fixed4 _Color;//两个Pass通用的顶点函数void vert_ui(inout appdata_ui Input, out v2f_ui Output){Output.pos = mul(UNITY_MATRIX_MVP, Input.vertex);Output.uv = Input.texcoord;#ifdef UNITY_HALF_TEXEL_OFFSETOutput.uv.xy += (_ScreenParams.zw-1.0)*float2(-1,1);#endifOutput.color = Input.color * _Color;}ENDCGSubShader{Tags{"Queue"="Transparent""IgnoreProjector"="True""RenderType"="Transparent""PreviewType"="Plane""CanUseSpriteAtlas"="True"}Stencil{Ref [_Stencil]Comp [_StencilComp]Pass [_StencilOp]ReadMask [_StencilReadMask]WriteMask [_StencilWriteMask]}Cull OffLighting OffZWrite OffZTest [unity_GUIZTestMode]Fog { Mode Off }Blend SrcAlpha OneMinusSrcAlphaColorMask [_ColorMask]Pass{//第一个Pass,正常渲染CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"v2f_ui vert(appdata_ui v){v2f_ui o;vert_ui(v, o);return o;}sampler2D _MainTex;fixed4 frag(v2f_ui i) : SV_Target{half4 color = tex2D(_MainTex, i.uv) * i.color;clip (color.a - 0.01);return color;}ENDCG}Pass{//第二个Pass,渲染水波CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _NoiseTex;float4 _Offset;half _SpeedX;half _SpeedY;half _Indentity;float _AlphaFadeIn;float _AlphaFadeOut;half _TwistFadeIn;half _TwistFadeOut;fixed _TwistFadeInIndentity;fixed _TwistFadeOutIndentity;v2f_ui vert(appdata_ui v){v2f_ui o;v.vertex = v.vertex - float4 (_Offset.xyz, 0);//偏移顶点坐标vert_ui(v, o);return o;}sampler2D _MainTex;fixed4 frag(v2f_ui i) : SV_Target{//对淡入强度和淡出强度的插值fixed fadeT = saturate((_TwistFadeOut - i.uv.y) / (_TwistFadeOut - _TwistFadeIn));float2 tuv = (i.uv - float2(0.5, 0)) * fixed2(lerp(_TwistFadeOutIndentity, _TwistFadeInIndentity, fadeT), 1) + float2(0.5, 0);//计算噪波贴图的RG值,得到扭曲UV,float2 waveOffset = (tex2D(_NoiseTex, tuv + float2(0, _Time.y * _SpeedY)).rg + tex2D(_NoiseTex, tuv + float2(_Time.y * _SpeedX, 0)).rg) - 1;float2 ruv = float2(i.uv.x, 1 - i.uv.y) + waveOffset * _Indentity;//使用扭曲UV对纹理采样float4 c = tex2D (_MainTex, ruv);//对淡入Alpha和淡出Alpha的插值fixed fadeA = saturate((_AlphaFadeOut - ruv.y) / (_AlphaFadeOut - _AlphaFadeIn));c = c * _Color * i.color * fadeA;clip (c.a - 0.01);return c;}ENDCG}}}


1 0
原创粉丝点击