Unity Shader实现新手引导遮罩镂空效果
作者:mac_zly 发布时间:2022-08-18 16:25:12
标签:Unity,遮罩,镂空
这两天实现了下新手引导需要的遮罩镂空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
}
}
}
来源:https://blog.csdn.net/tracyzly/article/details/80279692


猜你喜欢
- 目录或库文件名中包含汉字或空格的话,请将其用半角双引号括住。项目、属性、C/C++、附加包含目录:填写附加头文件所在目录 分号间隔多项项目、
- 开发Android程序时,有时候在程序运行的时候,不能让系统休眠,否则有一些运行会停止,因此我们需要设置禁止休眠,有两种方式: &
- 目录前言1、什么叫循环依赖呢2、具体出现循环依赖的代码逻辑3、解决循环依赖的代码实现总结前言本文基于springboot版本2.5.1 &n
- Task执行任务,等待任务完成代码://任务Func<int> Funcs = () =>{? ? Console.Wri
- Stripe支付首页需要引用Stripe.net框架,我引用的是22.8.0版本,注意.NETFramework的版本为4.5,同时需要引用
- 博主第一次安装Android Studio 3.6版本的时候就找不到R.java文件,于是在网上找个各种方法,但是都没能解决问题。注意:本博
- @ApiImplicitParam作用在方法上,表示单独的请求参数参数name:参数名。value:参数的具体意义,作用。required:
- 本文告诉大家如何使用相同权限调用cmd并且传入命令。如果想要用相同的权限运行一个程序,可以使用 ProcessStartInfo 的方法&n
- CAS原理在计算机科学中,比较和交换(Compare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较
- 本文实例为大家分享了Unity实现切割图集工具的具体代码,供大家参考,具体内容如下操作步骤先将脚本拖入Editor1.选中要切割的图片,te
- 约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;
- 背景Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。Timsort一直
- 在你布局或者组件混用的时候你可能会发现 gridview 的九宫格没有完全在页面上显示,只是显示了一个局部(第一行)只有一个滚动条,还不能上
- 开发工具 :idea工程结构:父工程father子模块 dao (用于持久化数据跟数据库交互)子模块 entity (实体类)子模块 ser
- -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M 这里有几个问
- System.ComponentModel.Design.DesignSurface是为设计组件提供一个用户界面,通过它可以实现一个简单的窗
- 前言上节在谈论Bean的实例化过程时,在说明实例化后阶段时只是粗略地看了一下populateBean,并未展开分析。本节接着populate
- 前言相信大家应该都有所体会,在以前我们要实现流动性布局,比较繁琐,Google开源了一个项目叫FlexboxLayout,相信大家都不陌生。
- 闲来无事,做了一个简单的抽奖转盘的ui实现,供大家参考package com.microchange.lucky; import andro
- 本文实例讲述了C#使用listView增删操作的方法。分享给大家供大家参考。具体分析如下:应用场景: C#中使用listView控件,实现动