当前位置: 移动技术网 > IT编程>开发语言>c# > Unity Shader实现新手引导遮罩镂空效果

Unity Shader实现新手引导遮罩镂空效果

2020年06月23日  | 移动技术网IT编程  | 我要评论

阿拉斯加雪橇犬和哈士奇的区别,大话腐女 未删减,欧阳淼淼扮演者

这两天实现了下新手引导需要的遮罩镂空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
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网