需求
为了节省性能替代particle system,用了一堆trick实现了 从OnEnable开始,delay一段时间,从头开始序列帧播放和颜色渐变。
写这篇博文,是为了……虽然效果拼拼凑凑出来了,但是知其然还得知其所以然,好好记录一下~好,小学生作文时间开始。
参考
《Unity Shader 入门精要》源码
https://github.com/candycat1992/Unity_Shaders_Book/blob/master/Assets/Shaders/Chapter11/Chapter11-ImageSequenceAnimation.shader
shader中主要运算部分
uv运算所需参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Properties { // 贴图 _MainTex ("Image Sequence", 2D) = "white" {} // 纵横数量 _HorizontalAmount ("Horizontal Amount", Int) = 4 _VerticalAmount ("Vertical Amount", Int) = 4 // 移动速度 _Speed ("Speed", Range(1, 100)) = 30 // 延迟出现 _Delay("Delay", Float) = 1
//……颜色参数见下
//被OnEnable时间 由c#脚本传入 [HideInInspector]_TimeOnEnable("TimeOnEnable", Float) = 0 }
|
frag函数 uv运算部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| float _time = _Time.y - _TimeOnEnable - _Delay;
float time = floor(_time * _Speed);
float row = floor(time / _HorizontalAmount) + 1; float column = time - row * _HorizontalAmount;
half2 uv = i.uv + half2(column, -row); uv.x /= _HorizontalAmount; uv.y /= _VerticalAmount;
fixed4 c = tex2D(_MainTex, uv);
|
颜色运算增加参数
1 2 3 4 5 6
| //颜色变化 _ChangeDuring1("ChangeDuring1", Range(0,1000)) = 1 _ChangeDuring2("ChangeDuring2", Range(0,1000)) = 2 _Color1("Color1", Color) = (1,0.4995675,0.4995675,0) _Color2("Color2", Color) = (0.2118362,0.1712803,0.7058823,0) _Color3("Color3", Color) = (0.2118362,0.1712803,0.7058823,0)
|
frag函数 颜色渐变
需求结果为Color1花费ChangeDuring1时间,变为Color2,之后再花ChangeDuring2时间,从Color2变到Color3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
float ori_lerp = _time / _ChangeDuring1;
float temp = 1.0 - ori_lerp;
float lerp = (1.0 - saturate( max(temp, 0)));
fixed4 color1 = _Color1 * (1.0 - lerp) + _Color2 * lerp;
float time2 = _time - _ChangeDuring1; float ori_lerp2 = time2 / _ChangeDuring2; float temp2 = 1.0 - ori_lerp2; float lerp2 = 1.0 - saturate(max(temp2, 0));
fixed4 color2 = color1 * (1.0-lerp2) + _Color3 * lerp2; c.rgb *= color2.rgb;
c.a *= saturate(ceil(max(0.0,_time))) * color2.a;
return c;
|
多一嘴关于_TimeOnEnable
//怎么让_Time.y和unity时间对应
1
| mat.SetFloat("_TimeOnEnable", Time.timeSinceLevelLoad);
|