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

作者:mac_zly 时间:2022-08-18 16:25:12 

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

效果:忽略渐变的蒙版,随便找的图片

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

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;

效果:

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

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);

效果:不知道为啥上传上来就有问题了,正常是没问题的

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

整个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
   }
 }
}

来源:https://blog.csdn.net/tracyzly/article/details/80279692

标签:Unity,遮罩,镂空
0
投稿

猜你喜欢

  • java实现读取、删除文件夹下的文件

    2021-12-06 20:07:48
  • SpringBoot常用数据库开发技术汇总介绍

    2023-11-11 09:39:22
  • Spring Boot应用程序同时支持HTTP和HTTPS协议的实现方法

    2022-01-10 16:50:43
  • Java实现马踏棋盘算法

    2023-03-05 04:30:46
  • Java中常见的5种WEB服务器介绍

    2022-08-02 08:45:50
  • C#操作串口通信协议Modbus的常用方法介绍

    2023-01-20 04:06:58
  • 如何修改FeginCilent定义的服务名到指定服务

    2022-07-05 05:49:05
  • Java 从互联网上爬邮箱代码示例

    2022-02-27 16:40:57
  • Java方法重载和重写原理区别解析

    2022-09-28 14:29:04
  • Redis6搭建集群并在SpringBoot中使用RedisTemplate的实现

    2023-10-31 14:48:05
  • java实现五子棋小游戏

    2021-12-25 06:58:56
  • 关于SpringBoot中controller参数校验的使用

    2023-02-24 04:24:10
  • 一篇文章带你入门Java修饰符

    2021-12-25 12:46:01
  • 使用Swing绘制动态时钟

    2023-11-24 07:05:12
  • 浅析Spring Security登录验证流程源码

    2023-03-22 01:46:44
  • Spring实战之使用注解实现声明式事务操作示例

    2021-08-19 07:16:07
  • SpringBoot中定时任务@Scheduled注解的使用解读

    2022-11-24 17:20:11
  • 教你如何编写简单的网络爬虫

    2023-06-01 08:58:30
  • IDEA中配置文件模板的添加方法

    2023-10-28 17:52:31
  • 浅谈C#与Java两种语言的比较

    2023-09-26 13:05:19
  • asp之家 软件编程 m.aspxhome.com