首页 > 其他分享 >【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)

时间:2022-12-13 15:08:29浏览次数:72  
标签:BorderFlow 流光 0.5 Shader 边框 Unity 区域 中心点 矩形


更新日期:2021年8月23日。
Github源码:​​​[点我获取源码]​

索引

  • ​​BorderFlow 边框流动​​
  • ​​思路分析​​
  • ​​流光区域​​
  • ​​流光区域的中心点​​
  • ​​流光区域的宽度、高度​​
  • ​​定义流光区域​​
  • ​​流光效果​​
  • ​​如何求一个二维点在一个矩形内​​
  • ​​流光效果的平滑​​
  • ​​流光动画​​

BorderFlow 边框流动

UI边框流动的效果非常常见,实现思路也五花八门,在此我就不贴网上的那些示例了,直接看我们最终的效果图:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_顺时针

思路分析

流光区域

我们首先将上下左右四个方向在流动的区域(青色)定义为​​流光区域​​​,其他的定义为​​非流光区域​​​,本质上也即是​​流光区域​​​叠加了一个​​流光颜色(比如这里的青色)​​​,​​非流光区域​​就按图像的正常颜色输出即可。

那么,我们要如何确定哪些是​​流光区域​​呢?

这个其实很简单,我们通过上方的效果图就可以看出来,​​流光区域​​实际上就是一个矩形区域而已,那么如何确定一个矩形区域?

在一个二维平面中,只要确定了一个​​中心点​​​(矩形的中心点),然后再确定了​​宽度​​​和​​高度​​,即可得到一个固定的矩形区域(我们不考虑旋转)。

众所周知,图像渲染就是一个不停输入与输出的过程,在这里我们不需要立即确定​​流光区域​​​的真正值,我们只需要制定一个规则,让​​流光区域​​根据输入的值和我们制定的规则进行实时定义即可,规则如何制定?我们继续往后看。

流光区域的中心点

通过反复研究效果图,我们发现​​流光区域​​​的位置并不是固定的,他会不停的以顺时针方向流动,以​​上、右​​​的流光作为一组,​​下、左​​的流光作为一组,规则如下:

(上、右)流光从上方的左侧开始​向右​流动,抵达右边界后,再次从​右方的上侧​开始​向下​移动,抵达下边界后,流动停止(由于这里使用了循环动画,所以流光再次从上方的左侧开始),另一组(下、左)流光雷同,方向依旧顺时针。

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_Unity_02


如果将整个流动的过程定义为​​x=1​​​的话,那么​​左上角​​​就是​​x=0​​​,​​右上角​​​就是​​x=0.5​​​,​​右下角​​​就是​​x=1​​​,如下图所示,整个流光的​​活动轨迹​​:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_Shader_03


那么,再次将流光区域看做一个​​矩形​​​,这个矩形的中心点(也即是流光区域的中心点)的x坐标便可以确定了,那便是我们上文的​​x​​值(活动轨迹)。

至于中心点的y值,我们不难发现,上下左右四个方向的流光都是紧贴边缘的,而图像的四个边缘坐标都是已知的(uv坐标系),则​​y​​值很明显可以直接求出来:

比如上方流光区域中心点y值 = 1 - 流光区域高度 * 0.5

由此得出流光区域的中心点为:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_Unity_04

流光区域的宽度、高度

中心点的规则确定了,那么再来看​​宽度​​​和​​高度​​。

通过再次研究效果图,我们可以很明显的发现,流光区域的宽度和高度没有规则可言,高度可以是任意值(当然不会大于图像的高度),宽度也是一样。

也就是说,​​宽度​​​和​​高度​​的值我们可以直接定义为输入变量即可。

定义流光区域

思路理清楚了,接下来我们直接写代码定义流光区域,先设定好输入值:

Properties
{
//流光位置:上文中流光的活动轨迹(0-1),也即是流光区域中心点的x坐标
//由于流光区域中心点的y坐标可以通过厚度求得,所以这里不设直接输入
_FlowPos("流光位置", Range(0, 1)) = 0
_FlowWidth("流光区域宽度", Range(0, 1)) = 0.3
_FlowThickness("流光区域高度", Range(0, 1)) = 0.03
}

然后根据我们前文中的规则,算出流光区域的真正​​矩形区域​​​所在(这里以​​上边框​​为例):

//根据规则,流光位置(_FlowPos)在0-0.5时,上边框的流光从左侧流动到右侧
//所以这里求出流光区域中心点的x坐标在整个上边框所占的比例 ratio
half ratio = smoothstep(0, 0.5, _FlowPos);

然后将流光区域中心点的x坐标比例 ratio 映射到图像上的真实位置:

//half realXPos = lerp(0, 1, ratio);
half realXPos = lerp(_FlowWidth * -0.5, 1 + _FlowWidth * 0.5, ratio);
half realYPos = 1 - _FlowThickness * 0.5;

这里有人可能会看不懂了,上边框从左至右的真实x值应该是0-1(注释那行),为什么这里却是另一个值呢?

很简单,看图你就明白了:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_顺时针_05


因为将上边框区间的左、右都拉伸半个流光区域宽度,会给人一种流光​从无到有​​从整到零​的过渡流动过程,不至于一开始就有半截的流光显示在图像上。

那么至此,我们已经求出了​​流光区域​​​的中心点,和已知的​​宽度​​​、​​高度​​,已然可以确定一个矩形区域,那么只要uv坐标在该区域的像素,就会被叠加流光效果,反之则无视。

流光效果

叠加​​流光效果​​​的过程就简单了,首先,我们还是希望​​流光效果​​的亮度和颜色都是可变的,所以我们再次新增输入参数:

Properties
{
//流光位置:上文中流光的活动轨迹(0-1),也即是流光区域中心点的x坐标
//由于流光区域中心点的y坐标可以通过厚度求得,所以这里不设直接输入
_FlowPos("流光位置", Range(0, 1)) = 0
_FlowWidth("流光区域宽度", Range(0, 1)) = 0.3
_FlowThickness("流光区域厚度", Range(0, 1)) = 0.03

_FlowColor("流光颜色", Color) = (1,1,1)
_FlowBrightness("流光亮度", Range(0, 1)) = 1
}

接下来,我们判断当前输入的像素点的uv坐标是否在​​流光区域矩形​​​内,在的话就叠加​​流光颜色​​​、​​流光亮度​​,不在的话,就原封不动输出。

//IsInRect:求一个二维点是否在一个矩形内
//第一个参数为一个矩形(half4 格式,四个值分别为【矩形中心点x坐标,矩形中心点y坐标,矩形宽度,矩形高度】)
//第二个参数为指定的二维点
//返回值:当输入的二维点在矩形区域内时,返回1,否则返回0
//在这里我们将亮度 _FlowBrightness * IsInRect的返回值,使得在流光区域内的返回亮度值,不在的返回0
half brightness = IsInRect(half4(realXPos , realYPos , _FlowWidth, _FlowThickness), uv) * _FlowBrightness;
//将流光颜色叠加到主颜色,如果不在流光区域内,则上方求得的亮度为0,则叠加无效
color.rgb += color.a * brightness * _FlowColor;

那么,求出来一个上边框以后,其他三个边框的算法也雷同了,只是​​流光区域​​​所在的​​矩形定义​​略有不同(比如计算右边框时,_FlowWidth 将成为高度,_FlowThickness 将成为宽度),这里就不再赘述了。

如何求一个二维点在一个矩形内

这里也即是​​IsInRect​​的具体实现,其实很简单,看下算法就明白了:

//求一个点是否在指定方形区域内
fixed IsInRect(half4 rect, half2 point2)
{
half width = rect.z * 0.5;
half height = rect.w * 0.5;
//如果点的位置没有超过方形区域左边界
fixed left = step(rect.x - width, point2.x);
//如果点的位置没有超过方形区域右边界
fixed right = step(point2.x, rect.x + width);
//如果点的位置没有超过方形区域上边界
fixed up = step(rect.y - height, point2.y);
//如果点的位置没有超过方形区域下边界
fixed down = step(point2.y, rect.y + height);
//则点在方形区域内(任何一边不满足,都将返回0)
return left * right * up * down;
}

流光效果的平滑

我们再次回看一下效果图,会发现​​流光区域​​​是呈现一个从右至左变淡的平滑效果的(上边框),也就是给人一种流动中的​​速度感​​:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_二维_06


这点要怎么实现?我们还是看代码,一行搞定:

//IsInRect:求一个二维点是否在一个矩形内
//第一个参数为一个矩形(half4 格式,四个值分别为【矩形中心点x坐标,矩形中心点y坐标,矩形宽度,矩形高度】)
//第二个参数为指定的二维点
//返回值:当输入的二维点在矩形区域内时,返回1,否则返回0
//在这里我们将亮度 _FlowBrightness * IsInRect的返回值,使得在流光区域内的返回亮度值,不在的返回0
half brightness = IsInRect(half4(realXPos , realYPos , _FlowWidth, _FlowThickness), uv) * _FlowBrightness;
//【新增的行】将流光区域平滑(使得越靠近区域右侧,流光强度越接近1,越靠近区域左侧,流光强度越接近0)
brightness *= smoothstep(0, _FlowWidth, uv.x - realXPos + _FlowWidth * 0.5);
//将流光颜色叠加到主颜色,如果不在流光区域内,则上方求得的亮度为0,则叠加无效
color.rgb += color.a * brightness * _FlowColor;

这里的​​uv.x - realXPos + _FlowWidth * 0.5​​​计算,将uv的x坐标映射到了(0,1),使得位于​​流光区域最左侧​​​的点​​映射为0​​​,​​流光区域最右侧​​​的点​​映射为1​​,从而生成了一个平滑区间的效果,将此平滑区间 * brightness ,便将叠加的流光颜色进行了平滑效果。

流光动画

要实现流光动画,很明显我们只需要改变输入的​​_FlowPos​​​值即可,不需要借助​​_Time​​参数,直接添加一个动画播放器:

【Unity Shader】Special Effects(二)BorderFlow 边框流动(UI)_二维_07


到此,这个简单的边框流动效果就基本完结了,如果还有不明白的地方可以查阅源码,当然,博客中的代码不一定与源码完全相同,这里的本意只是介绍思路,具体的实现过程中可能有一些语句上的优化,当然核心算法是一样的。


标签:BorderFlow,流光,0.5,Shader,边框,Unity,区域,中心点,矩形
From: https://blog.51cto.com/u_15911199/5934124

相关文章

  • Unity插件 - MeshEditor(五) 网格顶点动画(变形动画)
        网格顶点动画(变形动画)是针对于物体的形状可以随意变换并记录为关键帧的动画,虽然模型的顶点数据还是应该交给GPU绘制才是正道,CPU刷新模型顶点始终是个吃力不讨好的事......
  • 【Unity】 HTFramework框架(四十)Debug的性能监控
    更新日期:2021年4月22日。Github源码:​​​[点我获取源码]​​​Gitee源码:​​[点我获取源码]​​索引​​C#代码性能监控​​​​使用​​​​Debug的性能监控模式​​​......
  • 【Unity】 HTFramework框架(四十二)【进阶篇】使用依赖注入(控制反转模式)
    更新日期:2022年1月4日。Github源码:​​​[点我获取源码]​​​Gitee源码:​​[点我获取源码]​​索引​​依赖注入​​​​使用​​​​InjectPath​​​​InjectUI​​​......
  • Unity UGUI图文混排源码(一)
    我从一开始想到的图文混排的概念都是通过文字间的空隙去粘贴一张图片,这样确定图片前面文字的最后一个位置变成了最主要的参数,接下来就给出两种解决方案首先,先发UGUI源码的一......
  • Unity UGUI基础之Text
    Text作为UGUI最基础的控件以及最常用的控件,它在项目中的应用绝对可以算是最多的,任何一个UI界面可以说都离不开它,它的基本属性如下:一、recttransform组件:recttransform(矩形......
  • Unity UGUI实现图文混排
    目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英文来说,并没有什么影响。然后对于中文来说就是一个相当麻烦......
  • Unity插件 - MeshEditor(十) 模型风力拉扯特效
    更新日期:2020年4月23日。 Github源码:​​​[点我获取源码]​​ 先上几张效果图:  (导演:我们需要一个刮风的效果,道具组,上大风扇) (导演:咔!!!行了,道具组你们明天不用来上班了) ......
  • Unity 纹理优化及TextureProcessor工具
    更新日期:2020年11月18日。Github源码:​​​[点我获取源码]​​索引​​纹理优化​​​​TextureProcessor工具​​​​使用​​​​Resizer纹理缩放器​​​​打开纹理缩放......
  • Unity插件 - MeshEditor(十一) 模型正弦扭曲特效
    更新日期:2020年4月23日。Github源码:​​​[点我获取源码]​​ 先上几张效果图:   OK,进入今天的正题吧,插一个正弦函数的话题进来: 首先,正弦函数曲线,如下:  在如上坐标系......
  • 【Unity】 HTFramework框架(三十九)UI的数据驱动模式,MVVM
    更新日期:2020年10月24日。Github源码:​​​[点我获取源码]​​​Gitee源码:​​[点我获取源码]​​索引​​UI的数据驱动模式​​​​使用​​​​数据模型​​​​Bindabl......