Unity Shader实现新手引导遮罩镂空效果
这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下。
1、圆形镂空shader代码:
//计算片元世界坐标和目标中心位置的距离 floatdis=distance(IN.worldPosition.xy,_Center.xy); //过滤掉距离小于(半径-过渡范围)的片元 clip(dis-(_Radius-_TransitionRange)); //优化if条件判断,如果距离小于半径则执行下一步,等于if(dis<_Radius) fixedtmp=step(dis,_Radius); //计算过渡范围内的alpha值 color.a*=(1-tmp)+tmp*(dis-(_Radius-_TransitionRange))/_TransitionRange;
效果:忽略渐变的蒙版,随便找的图片
2、椭圆镂空shader代码:
//计算X轴方向距离 floatdisX=distance(IN.worldPosition.x,_Center.x); //计算Y轴方向距离 floatdisY=distance(IN.worldPosition.y,_Center.y); //运用椭圆方程计算片元的alpha值,_Ellipse为椭圆系数 fixedfactor=clamp(pow(abs(disX/_Width),_Ellipse)+pow(abs(disY/_Height),_Ellipse),0.0,1.0); //优化if条件判断 fixedtmp=step(factor,1.0f); //赋值椭圆外或椭圆内的alpha值 color.a*=(1-tmp)+tmp*factor;
效果:
3、圆形目标位置聚合动画shader代码:
//_StartTime为效果开始时间点,Unity中对应赋值material.SetFloat("_StartTime",Time.timeSinceLevelLoad); fixedprocessTime=_Time.y-_StartTime; //判断shader执行时长是否超过_TotalTime clip(_TotalTime-processTime); //优化if条件判断 fixedtmp=step(processTime,_ReduceTime); //计算当前时间点的圆形镂空半径 floatcurRadius=(1-tmp)*_Radius+tmp*(_MaxRadius-(_MaxRadius-_Radius)*processTime/_ReduceTime); floatdis=distance(IN.worldPosition.xy,_Center.xy); //抛弃距离小于当前圆形镂空半径的片元 clip(dis-curRadius);
效果:不知道为啥上传上来就有问题了,正常是没问题的
整个shader源码,在UnityUGUI自带Defaultshader基础上添加:
//Unitybuilt-inshadersource.Copyright(c)2016UnityTechnologies.MITlicense(seelicense.txt) Shader"UI/Default_Mask" { Properties { [PerRendererData]_MainTex("SpriteTexture",2D)="white"{} _Color("Tint",Color)=(1,1,1,1) _StencilComp("StencilComparison",Float)=8 _Stencil("StencilID",Float)=0 _StencilOp("StencilOperation",Float)=0 _StencilWriteMask("StencilWriteMask",Float)=255 _StencilReadMask("StencilReadMask",Float)=255 _ColorMask("ColorMask",Float)=15 [Toggle(UNITY_UI_ALPHACLIP)]_UseUIAlphaClip("UseAlphaClip",Float)=0 //-------------------add---------------------- _Center("Center",vector)=(0,0,0,0) _Radius("Radius",Range(0,1000))=1000//sliders _TransitionRange("TransitionRange",Range(0,100))=10 _Width("Width",Float)=1 _Height("Height",Float)=1 _Ellipse("Ellipse",Float)=4 _ReduceTime("ReduceTime",Float)=1 _TotalTime("TotalTime",Float)=1 _StartTime("StartTime",Float)=0 _MaxRadius("MaxRadius",Float)=1500 [KeywordEnum(ROUND,ELLIPSE,DYNAMIC_ROUND)]_RoundMode("Maskmode",Float)=0 //-------------------add---------------------- } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Stencil { Ref[_Stencil] Comp[_StencilComp] Pass[_StencilOp] ReadMask[_StencilReadMask] WriteMask[_StencilWriteMask] } CullOff LightingOff ZWriteOff ZTest[unity_GUIZTestMode] BlendSrcAlphaOneMinusSrcAlpha ColorMask[_ColorMask] Pass { Name"Default" CGPROGRAM #pragmavertexvert #pragmafragmentfrag #pragmatarget2.0 #include"UnityCG.cginc" #include"UnityUI.cginc" #pragmamulti_compile__UNITY_UI_CLIP_RECT #pragmamulti_compile__UNITY_UI_ALPHACLIP #pragmamulti_compile_ROUNDMODE_ROUND_ROUNDMODE_ELLIPSE_ROUNDMODE_DYNAMIC_ROUND structappdata_t { float4vertex:POSITION; float4color:COLOR; float2texcoord:TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; structv2f { float4vertex:SV_POSITION; fixed4color:COLOR; float2texcoord:TEXCOORD0; float4worldPosition:TEXCOORD1; UNITY_VERTEX_OUTPUT_STEREO }; fixed4_Color; fixed4_TextureSampleAdd; float4_ClipRect; //-------------------add---------------------- half_Radius; float2_Center; half_TransitionRange; half_Width; half_Height; half_Ellipse; fixed_ReduceTime; half_TotalTime; float_StartTime; half_MaxRadius; //-------------------add---------------------- v2fvert(appdata_tv) { v2fOUT; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); OUT.worldPosition=v.vertex; OUT.vertex=UnityObjectToClipPos(OUT.worldPosition); OUT.texcoord=v.texcoord; OUT.color=v.color*_Color; returnOUT; } sampler2D_MainTex; fixed4frag(v2fIN):SV_Target { half4color=(tex2D(_MainTex,IN.texcoord)+_TextureSampleAdd)*IN.color; #ifdefUNITY_UI_CLIP_RECT color.a*=UnityGet2DClipping(IN.worldPosition.xy,_ClipRect); #endif #ifdefUNITY_UI_ALPHACLIP clip(color.a-0.001); #endif //-------------------add---------------------- #ifdef_ROUNDMODE_ROUND //计算片元世界坐标和目标中心位置的距离 floatdis=distance(IN.worldPosition.xy,_Center.xy); //过滤掉距离小于(半径-过渡范围)的片元 clip(dis-(_Radius-_TransitionRange)); //优化if条件判断,如果距离小于半径则执行下一步,等于if(dis<_Radius) fixedtmp=step(dis,_Radius); //计算过渡范围内的alpha值 color.a*=(1-tmp)+tmp*(dis-(_Radius-_TransitionRange))/_TransitionRange; #elif_ROUNDMODE_ELLIPSE //计算X轴方向距离 floatdisX=distance(IN.worldPosition.x,_Center.x); //计算Y轴方向距离 floatdisY=distance(IN.worldPosition.y,_Center.y); //运用椭圆方程计算片元的alpha值,_Ellipse为椭圆系数 fixedfactor=clamp(pow(abs(disX/_Width),_Ellipse)+pow(abs(disY/_Height),_Ellipse),0.0,1.0); //优化if条件判断 fixedtmp=step(factor,1.0f); //赋值椭圆外或椭圆内的alpha值 color.a*=(1-tmp)+tmp*factor; #else //_StartTime为效果开始时间点,Unity中对应赋值material.SetFloat("_StartTime",Time.timeSinceLevelLoad); fixedprocessTime=_Time.y-_StartTime; //判断shader执行时长是否超过_TotalTime clip(_TotalTime-processTime); //优化if条件判断 fixedtmp=step(processTime,_ReduceTime); //计算当前时间点的圆形镂空半径 floatcurRadius=(1-tmp)*_Radius+tmp*(_MaxRadius-(_MaxRadius-_Radius)*processTime/_ReduceTime); floatdis=distance(IN.worldPosition.xy,_Center.xy); //抛弃距离小于当前圆形镂空半径的片元 clip(dis-curRadius); #endif //-------------------add---------------------- returncolor; } ENDCG } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。