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

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

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

(0)

相关推荐

  • Unity3D Shader实现动态屏幕遮罩

    屏幕可视范围跟随目标物体移动,可修改可视范围大小,边缘渐变大小.以及遮罩颜色,支持最高物体数量可在Shader中修改,当前版本支持最多9个物体. 效果图如下: 控制面板如下: Shader代码如下: Shader "Peter/DarkEffect" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // No culling or depth Cull Off

  • Unity shader实现遮罩效果

    本文实例为大家分享了Unity shader实现遮罩效果的具体代码,供大家参考,具体内容如下 效果: shader代码: Shader "Custom/Mask" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {}//目标图片,即需要被遮罩的图片 _MaskLayer("Culling Mask",2D) = "white"{}//混合的图片,设置

  • Unity实现新手引导镂空效果

    本文实例为大家分享了Unity实现新手引导镂空效果的具体代码,供大家参考,具体内容如下 一.实现思路 创建有8个顶点的Mesh,内外边界都是四边形(矩形).只生成内.外边之间的Mesh,内层矩形就产生了镂空部分,外层的4个顶点,是组件自身RectTransform的四个顶点,内层的4个顶点,使用镂空目标(_target)RectTransform的四个顶点.确定内层的顶点的时候需要注意,多数情况下_target和HollowOutMask都不在同一个本地坐标空间,所以需要使用CalculateR

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

    这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下. 1.圆形镂空shader代码:  //计算片元世界坐标和目标中心位置的距离 float dis = distance(IN.worldPosition.xy, _Center.xy); //过滤掉距离小于(半径-过渡范围)的片元 clip(dis - (_Radius - _TransitionRange)); //优化if条件判断,如果距离小于半径则执行下一步,等于if(dis < _Radius) fixed tmp = st

  • Unity shader实现自由放大缩小效果

    本文实例为大家分享了Unity shader实现自由放大缩小效果的具体代码,供大家参考,具体内容如下 代码: 以下实现的shader代码: Shader "Hidden/Wave" { Properties { _MainTex ("Texture", 2D) = "white" {} _WaveWidth("Wave Width",float) = 0.5 _CenterX("CenterX",float

  • Unity Shader实现3D翻页效果

    本文实例为大家分享了Unity Shader实现3D翻页效果的具体代码,供大家参考,具体内容如下 参考文章:UnityShader使用Plane实现翻书效果 效果图: 原理:Shader顶点动画 在顶点着色器进行对顶点Y值的偏移(使用了Sin函数模拟翻页时产生的弯曲),对顶点X值的偏移实现纸张在翻页时的收缩(一般是不用收缩),最后对顶点进行围绕Z轴旋转实现Plane翻页(Z轴是本例的旋转轴,请根据你具体情况修改,上面的两个偏移同理). Shader "Unlit/PaperTurnMilkSha

  • Unity shader实现顶点动画波动效果

    本文实例为大家分享了Unity shader实现顶点动画的具体代码,供大家参考,具体内容如下 需要了解的背景知识: 波动实例:y=  Asin(ωx+φ) φ:决定波形与X轴位置关系或横向移动距离(左加右减) ω:决定周期(最小正周期T=2Π/|ω|) A:决定峰值(纵向拉伸压缩的倍数) 顶点着色器的主要计算: 1.顶点位置 2.矩阵转换 片段着色器 1.纹理寻址 2.灯光作用 _Time表示时间周期 float4(t/20,  t,  t*2,  t*3) Shader "Custom/Wav

  • Unity Shader实现纹理遮罩效果

    纹理遮罩用处很多,简单来讲就是允许我们可以保护模型中的某些区域不受某些因素的影响.例如我们有时希望模型表面某些区域的反光强烈一些,而某些区域弱一些.为了得到更加细腻的结果,我们需要用一张遮罩纹理来控制该光照.还有一些情况就是某些模型需要多张纹理混合时,此时使用遮罩纹理可以控制如何混合这些纹理. 具体流程为:通过采样得到遮罩纹理的纹素值,然后使用其中某个或者几个通道的值来与某种表面属性进行相乘.当该通道的值为0时,此时该表面属性不受遮罩纹理的影响. shader代码如下: Shader "Cust

  • Unity shader实现消融效果

    本文实例为大家分享了Unity shader实现消融效果的具体代码,供大家参考,具体内容如下 效果图: shader代码: // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/EdgeColo" { Properties { _MainTex ("Texture", 2D) = "white" {} _N

  • Unity Shader实现序列帧动画效果

    本文实例为大家分享了Unity Shader序列帧动画效果的具体代码,供大家参考,具体内容如下   实现原理 主要的思想是设置显示UV纹理的大小,并逐帧修改图片的UV坐标.(可分为以下四步) 1.我们首先把 _Time.y 和速度属性_Speed 相乘来得到模拟的时间,并使用CG 的floor 函数对结果值取整来得到整数时间time 2.然后,我们使用time 除以_HorizontalAmount 的结果值的商来作为当前对应的行索引,除法结果的余数则是列索引. 3.接下来,我们需要使用行列索引

  • Unity Shader实现翻书效果

    今天实现一个简单的翻书的效果,话不多说,先上一张效果图: 这里就随便用的一张纹理了,我们还是称为"翻木板"吧,哈哈. 实现过程: 其实这个效果实现起来还是挺简单的,大概思路其实就是 让所有顶点都绕Z轴旋转,并且通过正余弦使之带有一点弧度. 下面开始让我们一步一步的实现该效果. 首先打开Unity新建一个工程,场景,并且创建一个名为openBookEffect的Shader文件,删掉原本多余的代码. 第一步,我们先让它绕z轴旋转起来 这里就要用到一个旋转矩阵了,让顶点左乘该矩阵,就能得到

随机推荐