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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。