这个效果我也不太好描述,不知道叫什么,看效果图吧:
这个是前两天刷抖音时看到的效果,所以今天有空来实现一下。
实现思路:
1、先选取一个旋转点,然后选定一个一次函数方程.
2、对这个一次函数方程进行旋转,获取新的一次函数方程,计算结果
3、根据结果,在线左边的显示一张图片,在右边的显示另一张图片
4、设置一个周期时间,在这个周期内反复更改角度,即可
具体实现步骤:
1、我先选择一个UV坐标点,这里我选择(0.5,1)这个点,我们叫它旋转点,我们选择一个一次函数方程,y=ax+b,因为这条直线会经过旋转点,且在某一时间会经过(0,0)点,将两点代入,即可求得a和b的值,=> a=2,b=0;
2、对一次函数绕点(m,n)进行旋转⊙角度,公式为:
顺时针旋转:
a' = (a - tan(⊙)) / (1 + a * tan(⊙));
b' = n - m * a'
逆时针旋转:
a' = (a + tan(⊙)) / (1 - a * tan(⊙));
b' = n - m * a'
根据旋转公式,我们可以求得新的a和b,即y = a'x + b'
3、根据新求出的一次函数方程,求出在某点y的坐标下,x的坐标值,然后如果图片的uv.x小于这个值,则显示第一张图片,大于这个值显示第二张图片
4、设置一个周期时间,比如1秒钟,然后计算出当前时间需要旋转的一个角度,即可
所有的步骤都已讲完,下面是所有的代码代码:
Shader "Unlit/Tiktok_RotChoiceShowTwoTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" { }
_SecondTex ("second Texture", 2D) = "white" { }
_line_A_value ("a value", float) = 0.5
_rot_angle ("rot angle", float) = 50.0
_rot_center_pos ("旋转中心", vector) = (0.5, 1.0, 0, 0)
_Cycle_Time ("循环时间", Range(0.1, 10)) = 3.0
_Min_Angle_value ("最小角度", float) = 0
_Max_Angle_value ("最大角度", float) = 50.0
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex: POSITION;
float2 uv: TEXCOORD0;
};
struct v2f
{
float2 uv: TEXCOORD0;
float4 vertex: SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _SecondTex;
float _line_A_value;
uniform float _rot_angle;
float4 _rot_center_pos;
float _Cycle_Time;
float _Min_Angle_value, _Max_Angle_value;
//求出是否是右边的像素,根据返回值显示第一张图片还是第二张图片
bool IsRightPixed(float2 uv, float rotAngle)
{
float ang = (UNITY_PI / 180.0) * rotAngle;
float tan_value = tan(ang);
float k1 = (_line_A_value + tan_value) / (1 - _line_A_value * tan_value);
float b1 = _rot_center_pos.y - _rot_center_pos.x * k1;
float x = (uv.y - b1) / k1;
if (x < uv.x)return false;
return true;
}
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i): SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
fixed4 secondCol = tex2D(_SecondTex, i.uv);
float total_angle = (_Max_Angle_value - _Min_Angle_value);//计算总角度
float per_second_rot_angle = total_angle / _Cycle_Time;//计算每秒旋转角度
float time = _Time.y % (_Cycle_Time * 2);
_rot_angle = _Min_Angle_value + per_second_rot_angle * time;//计算当前角度
if (_rot_angle >= _Max_Angle_value)//如果大于最大限制角度,则需要逆旋转,这样才可以周期摆动
_rot_angle = _Max_Angle_value * 2 - _rot_angle;
bool isRightPixed = IsRightPixed(i.uv, _rot_angle);
if (isRightPixed)
{
return secondCol;
}
return col;
}
ENDCG
}
}
}