Unity ShaderSpecial EffectsShiny 闪亮(UI)
Posted 神码编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity ShaderSpecial EffectsShiny 闪亮(UI)相关的知识,希望对你有一定的参考价值。
更新日期:2021年9月2日。
Github源码:[点我获取源码]
Shiny 闪亮
Shiny以另一种方式实现了LOGO流光,在表现效果上与其相差无几,不同的地方是Shiny不需要指定流光遮罩以及流动的图片纹理等,他是直接通过UV计算出一块区域,然后叠加颜色,以达到亮闪闪的效果,最终的效果图:
思路分析
首先,按照LOGO流光的思路,我们只需要选出一片uv区域,为区域叠加颜色,并使得区域的中心越亮
,越往区域的两边扩散越暗
,在不考虑动画的情况下,这便是我们想要的区域闪亮效果了。
因为要给人一种一闪而过的感觉,所以我们的闪亮区域
必定是上下贯通(左右移动)或者左右贯通(上下移动)的情况,如上文的最终效果图,闪亮区域便是上下贯通的,进行左右移动达到一闪而过的效果。
闪亮区域
我们先考虑上下贯通的方式,设想中,我们的闪亮区域如下:
我们将闪亮的值
想象为0-1
,则区域最中心为1(最亮),越往两边扩散就越接近0(最暗):
根据经验,很明显我们这里可以使用uv的横坐标来转换至闪亮的值
,已知uv的横坐标值区间如下:
那么我们的算法便明确了,即是将区间[0,1](也即是uv.x的取值范围)
映射为区间[0,1,0]
!
首先,区间[0,1]
可以进一步抽象为区间[0,0.5,1]
,然后,先将区间[0,0.5,1]
映射至区间[-1,0,1]
:
//将区间[0,0.5,1],映射到区间[-1,0,1]
half value1 = uv.x * 2 - 1;
然后再将区间[-1,0,1]
,通过取绝对值映射到区间[1,0,1]
:
//将区间[0,0.5,1],映射到区间[-1,0,1]
half value1 = uv.x * 2 - 1;
//将区间[-1,0,1],映射到区间[1,0,1]
half value2 = abs(value1);
最后,将区间[1,0,1]
倒置,便得到我们的所求结果,区间[0,1,0]
:
//将区间[0,0.5,1],映射到区间[-1,0,1]
half value1 = uv.x * 2 - 1;
//将区间[-1,0,1],映射到区间[1,0,1]
half value2 = abs(value1);
//倒置区间[1,0,1],得到区间[0,1,0]
half value3 = 1 - value2;
到这里,得到的值value3
便是一个根据当前输入的uv.x值,返回的闪亮的值
,此值的区间为[0,1,0]
,中间亮,两边暗。
柔和度
我们可以使用如下方式将值value3 [0,1,0]
进行平滑,得到的power
就是我们最终的闪亮强度:
//通过smoothstep将区间[0,1,0]平滑,得到闪亮强度power
half power = smoothstep(0, softness, value3);
这里的softness
是外部输入的值,我们命名为柔和度
,柔和度为何能够达到平滑效果呢?我们看图分析一下。
首先,当柔和度最低时(这里是0.01),效果上表现为完全不柔和
:
我们分析一下公式,将柔和度0.01带入:
//通过smoothstep将区间[0,1,0]平滑,得到闪亮强度power
half power = smoothstep(0, 0.01, value3);
根据smoothstep
方法特性,只要输入值value3
值大于0.01的,都会返回1,赋予power
,也即是说,经过一轮平滑运算,我们原本的value3
区间:
//扩大区间细节
[0,0.1,0.2,...0.9,1,0.9...0.2,0.1,0]
被转换为了power
区间:
//扩大区间细节
[0,1,1,...1,1,1...1,1,0]
也即是说,极低柔和度使得所有稍微有一点亮度
的地方,都变为了亮度为1
,这便是柔和度的体现。
反之,当柔和度最高时(这里是1),此平滑运算将返回value3
原值,他本身就是一个带有平滑效果的区间:
光泽度
由上文我们已经求得了闪亮的亮度值power
,我们将亮度值乘以一个颜色
,便得到我们最终的闪亮颜色了,在这里,我们再度引入一个控制参数光泽度
,用他来控制我们输出的颜色值:
//通过光泽度插值得到闪光颜色shinyColor
half3 shinyColor = lerp(fixed3(1, 1, 1), color.rgb, gloss);
//输出最终颜色(原始颜色 + 闪亮颜色)
color.rgb += shinyColor * power;
这里的光泽度gloss
在纯白色
与本身颜色
之间插值,当光泽度为0,闪亮颜色为白色(三通道值相等,乘以power
后会被降低部分值),任意颜色的三通道RGB
累加上相同的值后,并不会改变其色相
,也就是说,他该是红色还是红色,该是蓝色还是蓝色,看起来就只是整体变亮了一点,没有光泽感:
当光泽度为1时,闪亮颜色为自身颜色,自身颜色累加自身颜色,这就使得红色的地方越红,蓝色的地方越蓝,极具光泽感:
旋转
如上的计算,我们得到的只是一个垂直的,上下贯通的闪亮区域
,我们想要将他任意旋转,比如下面这样:
这样:
这样:
如何实现这样的效果呢?
我们再回想一下最开始求得闪亮区域的算法:输入一个uv坐标,根据uv坐标的x值求得此坐标点的闪亮颜色强度
。
我们要实现旋转效果,直接将uv坐标旋转
后再输入,输出的不就是该uv坐标的真实坐标点的闪亮颜色强度
!
所以算法很简单,说干就干,直接转一下uv:
//uv旋转
uv = RotatePoint2(uv, float2(0.5, 0.5), radians(_Rotation));
RotatePoint2的功能是沿着一个圆心,将输入的二维点旋转指定弧度:
//将二维顶点point2,沿着圆心center,顺时针旋转radian弧度
float2 RotatePoint2(float2 point2, float2 center, half radian)
half radius = distance(point2, center);
half angle = atan((point2.y - center.y) / (point2.x - center.x)) - radian;
point2.x = cos(angle) * radius + center.x;
point2.y = sin(angle) * radius + center.y;
return point2;
算法也即是三角函数,这里就不做详解了。
闪亮动画
要实现闪亮动画,我们只需要改变输入的_Position
值即可,不需要借助_Time
参数,直接添加一个动画播放器:
到此,这个简单的闪亮效果就基本完结了,如果还有不明白的地方可以查阅源码,当然,博客中的代码不一定与源码完全相同,这里的本意只是介绍思路,具体的实现过程中可能有一些语句上的优化,当然核心算法是一样的。
以上是关于Unity ShaderSpecial EffectsShiny 闪亮(UI)的主要内容,如果未能解决你的问题,请参考以下文章
Unity ShaderSpecial EffectsScan 扫描(UI)
Unity ShaderSpecial EffectsScan 扫描(UI)
Unity ShaderSpecial EffectsScan 扫描(UI)
Unity ShaderSpecial EffectsCorrect 色彩修正(UI)