Unity Shader实现新手引导遮罩镂空效果
程序员文章站
2023-11-14 17:07:16
这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下。1、圆形镂空shader代码://计算片元世界坐标和目标中心位置的距离float dis = distance(in.worldposi...
这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下。
1、圆形镂空shader代码:
//计算片元世界坐标和目标中心位置的距离 float dis = distance(in.worldposition.xy, _center.xy); //过滤掉距离小于(半径-过渡范围)的片元 clip(dis - (_radius - _transitionrange)); //优化if条件判断,如果距离小于半径则执行下一步,等于if(dis < _radius) fixed tmp = step(dis, _radius); //计算过渡范围内的alpha值 color.a *= (1 - tmp) + tmp * (dis - (_radius - _transitionrange)) / _transitionrange;
效果:忽略渐变的蒙版,随便找的图片
2、椭圆镂空shader代码:
//计算x轴方向距离 float disx = distance(in.worldposition.x, _center.x); //计算y轴方向距离 float disy = distance(in.worldposition.y, _center.y); //运用椭圆方程计算片元的alpha值,_ellipse为椭圆系数 fixed factor = clamp(pow(abs(disx / _width), _ellipse) + pow(abs(disy / _height), _ellipse), 0.0, 1.0); //优化if条件判断 fixed tmp = step(factor, 1.0f); //赋值椭圆外或椭圆内的alpha值 color.a *= (1 - tmp) + tmp * factor;
效果:
3、圆形目标位置聚合动画shader代码:
//_starttime为效果开始时间点,unity中对应赋值material.setfloat("_starttime", time.timesincelevelload); fixed processtime = _time.y - _starttime; //判断shader执行时长是否超过_totaltime clip(_totaltime - processtime); //优化if条件判断 fixed tmp = step(processtime, _reducetime); //计算当前时间点的圆形镂空半径 float curradius = (1 - tmp) * _radius + tmp * (_maxradius - (_maxradius - _radius) * processtime / _reducetime); float dis = distance(in.worldposition.xy, _center.xy); //抛弃距离小于当前圆形镂空半径的片元 clip(dis - curradius);
效果:不知道为啥上传上来就有问题了,正常是没问题的
整个shader源码,在unity ugui 自带default shader基础上添加:
// unity built-in shader source. copyright (c) 2016 unity technologies. mit license (see license.txt) shader "ui/default_mask" { properties { [perrendererdata] _maintex ("sprite texture", 2d) = "white" {} _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 [toggle(unity_ui_alphaclip)] _useuialphaclip ("use alpha clip", float) = 0 //-------------------add---------------------- _center("center", vector) = (0, 0, 0, 0) _radius("radius", range(0,1000)) = 1000 // sliders _transitionrange("transition range", 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("mask mode", 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] } cull off lighting off zwrite off ztest [unity_guiztestmode] blend srcalpha oneminussrcalpha colormask [_colormask] pass { name "default" cgprogram #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "unitycg.cginc" #include "unityui.cginc" #pragma multi_compile __ unity_ui_clip_rect #pragma multi_compile __ unity_ui_alphaclip #pragma multi_compile _roundmode_round _roundmode_ellipse _roundmode_dynamic_round struct appdata_t { float4 vertex : position; float4 color : color; float2 texcoord : texcoord0; unity_vertex_input_instance_id }; struct v2f { float4 vertex : sv_position; fixed4 color : color; float2 texcoord : texcoord0; float4 worldposition : 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---------------------- v2f vert(appdata_t v) { v2f out; 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; return out; } sampler2d _maintex; fixed4 frag(v2f in) : sv_target { half4 color = (tex2d(_maintex, in.texcoord) + _texturesampleadd) * in.color; #ifdef unity_ui_clip_rect color.a *= unityget2dclipping(in.worldposition.xy, _cliprect); #endif #ifdef unity_ui_alphaclip clip (color.a - 0.001); #endif //-------------------add---------------------- #ifdef _roundmode_round //计算片元世界坐标和目标中心位置的距离 float dis = distance(in.worldposition.xy, _center.xy); //过滤掉距离小于(半径-过渡范围)的片元 clip(dis - (_radius - _transitionrange)); //优化if条件判断,如果距离小于半径则执行下一步,等于if(dis < _radius) fixed tmp = step(dis, _radius); //计算过渡范围内的alpha值 color.a *= (1 - tmp) + tmp * (dis - (_radius - _transitionrange)) / _transitionrange; #elif _roundmode_ellipse //计算x轴方向距离 float disx = distance(in.worldposition.x, _center.x); //计算y轴方向距离 float disy = distance(in.worldposition.y, _center.y); //运用椭圆方程计算片元的alpha值,_ellipse为椭圆系数 fixed factor = clamp(pow(abs(disx / _width), _ellipse) + pow(abs(disy / _height), _ellipse), 0.0, 1.0); //优化if条件判断 fixed tmp = step(factor, 1.0f); //赋值椭圆外或椭圆内的alpha值 color.a *= (1 - tmp) + tmp * factor; #else //_starttime为效果开始时间点,unity中对应赋值material.setfloat("_starttime", time.timesincelevelload); fixed processtime = _time.y - _starttime; //判断shader执行时长是否超过_totaltime clip(_totaltime - processtime); //优化if条件判断 fixed tmp = step(processtime, _reducetime); //计算当前时间点的圆形镂空半径 float curradius = (1 - tmp) * _radius + tmp * (_maxradius - (_maxradius - _radius) * processtime / _reducetime); float dis = distance(in.worldposition.xy, _center.xy); //抛弃距离小于当前圆形镂空半径的片元 clip(dis - curradius); #endif //-------------------add---------------------- return color; } endcg } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: C#面向对象之封装
下一篇: 高性能MySQL--创建高性能的索引