用了几天弄明白了这个简单的进度条,不容易。
主要是利用了三角函数反正切函数特性,在夹角范围内的值透明度设为0,不在范围内值设成1.
对于shader 编辑器,可以用forge 以及amplify.
贴上测试代码:
// Made with Amplify Shader Editor
// Available at the Unity Asset Store - http://u3d.as/y3X
Shader "Unlit/MT"
{
Properties
{
_MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_angle("angle", Float) = 360
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
};
uniform fixed4 _Color;
uniform fixed4 _TextureSampleAdd;
uniform float4 _ClipRect;
uniform sampler2D _MainTex;
uniform float _angle;
v2f vert( appdata_t IN )
{
v2f OUT;
OUT.worldPosition = IN.vertex;
OUT.worldPosition.xyz += float3( 0, 0, 0 ) ;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0) * float2(-1,1) * OUT.vertex.w;
#endif
OUT.color = IN.color * _Color;
return OUT;
}
fixed4 frag(v2f IN ) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
float2 uv = IN.worldPosition.xy - float2(0.5,0.5);
float ang = degrees(atan2(-uv.x,-uv.y)) + 180;
//color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
color.a *= saturate((ang -_angle));
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}/*ASEBEGIN
Version=13101
-116;157;1203;692;-46.31354;498.8189;1;True;True
Node;AmplifyShaderEditor.VertexToFragmentNode;29;541.0544,-68.96652;Float;False;1;0;COLOR;0.0;False;1;COLOR
Node;AmplifyShaderEditor.TemplateShaderPropertyNode;26;297.6875,-356.4916;Float;False;_TextureSampleAdd;0;1;FLOAT4
Node;AmplifyShaderEditor.RangedFloatNode;31;558.3135,-433.8189;Float;False;Property;_angle;angle;2;0;0;0;360;0;1;FLOAT
Node;AmplifyShaderEditor.SimpleMultiplyOpNode;23;65.14954,-236.1854;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT
Node;AmplifyShaderEditor.RangedFloatNode;21;-297.8843,-0.2657361;Float;False;Property;_Float1;Float 1;0;0;1;0;1;0;1;FLOAT
Node;AmplifyShaderEditor.VertexColorNode;30;307.9329,-207.2095;Float;True;0;5;COLOR;FLOAT;FLOAT;FLOAT;FLOAT
Node;AmplifyShaderEditor.RangedFloatNode;20;-306.7811,-256.8852;Float;False;Property;_Float0;Float 0;0;0;1;0;1;0;1;FLOAT
Node;AmplifyShaderEditor.TemplateShaderPropertyNode;28;797.5407,-125.9253;Float;False;_MainTex;0;1;SAMPLER2D
Node;AmplifyShaderEditor.TemplateMasterNode;19;635.5049,-337.8733;Float;False;True;2;Float;ASEMaterialInspector;0;3;Unlit/MT;5056123faa0c79b47ab6ad7e8bf059a4;2;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;0
WireConnection;29;0;30;0
WireConnection;23;0;20;0
WireConnection;23;1;21;0
ASEEND*/
//CHKSM=DF3770DDB144812ECE4D05E6DD7C43AB6637926F
参考:1 https://blog.csdn.net/u014761712/article/details/54882184
进度条shader 如下,创建三层Ui,第一层是外层蓝色,里层是那一个半透明的层,中间是那个绿色进度条添加下面的shader 的材质。通过外部设置shader “_Angle” 参数的改变来控制进度条。
求反正切的函数atan(double x)与atan2(double y,double x) 他们返回的值是弧度 要转化为角度再自己处理下。
前者接受的是一个正切值(直线的斜率)得到夹角,但是由于正切的规律性本可以有两个角度的但它却只返回一个,因为atan的值域是从-90~90 也就是它只处理一四象限,所以一般不用它。
第二个atan2(double y,double x) 其中y代表已知点的Y坐标 同理x ,返回值是此点与远点连线与x轴正方向的夹角,这样它就可以处理四个象限的任意情况了,它的值域相应的也就是-180~180了
例如:
- 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
参考2:http://www.it610.com/article/3578678.htm
技能CD特效
这个效果主要是利用反正切函数完成。atan2(x,y)的返回值是[-PI,PI],这个支持4个象限的反正切函数。关于圆角计算,在上篇文章中有介绍。
现在,我们来看看反正切函数的效果:
在第一象限:返回[0,PI/2],有渐变;
在第二象限:返回[PI/2,PI],为白色;
在第三象限:返回[-PI,-PI/2],为黑色;
在第四象限:返回[-PI/2,0],为黑色;
uv = i.uv - fixed2(0.5,0.5); float hui = atan2(uv.y, uv.x); return float4(hui,hui,hui,alpha);
反正切的返回值在[-PI,PI],那么我们现在增加变量_angle,让他控制反正切的值;我们设置_angle值为[-PI,PI],用_angle的值,加上反正切的值,他们最后的值就会随着_angle的值变化。
当_angle = -PI时,最终值为[-2PI,0],显示黑色;
当_angle = PI时,最终值为[0,2PI],显示渐变;
现在我使用用sign函数,将大于0的部分全部设置为1,小于等于0的部分设置成为0;
源代码:
Shader "JQM/Test02" { Properties { _MainTex ("Texture", 2D) = "white" {} _angle("angle", Range(0, 1)) = 0 } SubShader { Pass { Tags {"Queue" = "Transparent"} ZWrite Off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float _percent; float _angle; sampler2D _MainTex; float4 _MainTex_ST; struct VertexOutPut { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; VertexOutPut vert (appdata_full v) { VertexOutPut o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.uv = v.texcoord.xy; return o; } fixed4 frag (VertexOutPut i) : COLOR { //圆角计算 float2 uv = i.uv.xy - float2(0.5,0.5); float rx = fmod(uv.x, 0.4); float ry = fmod(uv.y, 0.4); float mx = step(0.4, abs(uv.x)); float my = step(0.4, abs(uv.y)); float alpha = 1 - mx*my*step(0.1, length(half2(rx,ry))); fixed4 col = tex2D(_MainTex, i.uv); uv = i.uv - fixed2(0.5,0.5); _angle = 6.283*(_angle-0.5); float hui =sign(_angle+atan2(uv.y, uv.x)); return float4(hui,hui,hui,alpha); } ENDCG } } }
CG函数
sign(x)
:如果 x 大于 0,返回 1;如果 x 小于 0,返回 01;否则返回 0。