如何制作融球加载动画?

基于SDF贴图的UI动效制作

Posted by Pavel on December 24, 2024

1. 前言

最近在pintrest上找到的参考挺有意思的打算在unity中使用shader复刻出来。 output (1).gif output (2).gif 最终在Unity中的效果

2.前期准备

2.1 贴图准备

融球的实现可以使用SDF计算,也可以选择使用贴图实现。针对这个效果,我在这里使用ps内描边制作了贴图。 1280X1280 (1).PNG

1280X1280 (2).PNG r通道是不动的四个圆,g通道是需要左右运动的圆,b通道存放表情。

3. UIShader

由于我没有按照UIshader的模板来写UIshader将会导致打包时不同机型产生各种各样的Bug。

在红米k30下: output.jpg

UI Shader与普通shader不一样,在Unity官方的UI-Defaut Shader中多了一些Tags他们有些是专为UI Shader提供的,并且需要关闭深度写入,深度测试选择[unity_GUIZTestMode]850X850.PNG

4. 实现思路

float2 moveUV = i.uv + float2(remap(sin(lerp(1.1,-1,i.vertexColor.r)),-1,1,0,0.65), 0);
float MoveBallMask = SAMPLE_TEXTURE2D(_MainTex,smh,moveUV).g;
float4 LoadingBalMask = SAMPLE_TEXTURE2D(_MainTex, smh, i.uv);
float combineBalls = saturate(LoadingBalMask.r + MoveBallMask);
combineBalls = saturate(remap(combineBalls,0.6,0.7,0,1));

float4 ballColor = lerp(_LoadBallColor,_WhereColor,MoveBallMask)*combineBalls;
float EmotionMove = MoveBallMask*LoadingBalMask.b;
ballColor = lerp(ballColor,_EyesColor,EmotionMove)*i.vertexColor.a;

简单来说,就是将每个圆的SDF数值相加然后再使用remap限制边缘,就可以得到融球的效果了,其他的还有让g通道圆沿u方向左右平移。

4.1 SDF

当然SDF的圆形图案也可以实时计算参考如下:

Inigo Quilez

4.2 Remap限制边缘

16fb508d-d789-424e-99c6-1a110021b714.png 主要用来将0~1的大范围值在小于0.6时为小于0,大于0.7时大于1,从而得到一个明确的边缘。

float remap(float x, float t1, float t2, float s1, float s2)
{
    float y = (x - t1)/(t2 - t1) * (s2 - s1)+ s1;
    return y;
}