1. 前言
最近在pintrest上找到的参考挺有意思的打算在unity中使用shader复刻出来。 最终在Unity中的效果
2.前期准备
2.1 贴图准备
融球的实现可以使用SDF计算,也可以选择使用贴图实现。针对这个效果,我在这里使用ps内描边制作了贴图。
r通道是不动的四个圆,g通道是需要左右运动的圆,b通道存放表情。
3. UIShader
由于我没有按照UIshader的模板来写UIshader将会导致打包时不同机型产生各种各样的Bug。
在红米k30下:
UI Shader与普通shader不一样,在Unity官方的UI-Defaut Shader中多了一些Tags他们有些是专为UI Shader提供的,并且需要关闭深度写入,深度测试选择[unity_GUIZTestMode]
。
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的圆形图案也可以实时计算参考如下:
4.2 Remap限制边缘
主要用来将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;
}