【Unity Shader】Special Effects(三)Shiny 闪亮(UI)

本文介绍了如何在Unity中创建Shiny闪亮效果,特别是针对UI元素如LOGO的流光效果。通过分析闪亮区域、柔和度、光泽度和旋转等关键步骤,详细阐述了Shader的实现思路。通过调整不同参数,可以实现闪亮区域的平滑过渡、颜色光泽以及动态动画效果。
摘要由CSDN通过智能技术生成

源码:[点我获取源码]

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)
{
	float2 dir = float2(0, 0) - center;
	point2 += dir;

	float2 newP;
	float c = cos(radian);
	float s = sin(radian);
	newP.x = point2.x * c - point2.y * s;
	newP.y = point2.x * s + point2.y * c;

	newP += (dir * -1);
	return newP;
}

闪亮动画

要实现闪亮动画,我们只需要改变输入的_Position值即可,不需要借助_Time参数,直接添加一个动画播放器:

在这里插入图片描述

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神码编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值