Shader动画
种类
序列帧动画
对贴图进行采样
滚动动画
顶点动画
最常用的
序列帧动画
过程上类似于赛璐璐动画的实现,一张贴图上均匀分布动画的不同帧数,配合缩放和位移进行采样即可
案例
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| Shader "Unlit/024" { Properties { _MainTex ("Texture", 2D) = "white" {} _HorAmount("HorAmount", float) = 4 _VerAmount("VerAmount", float) = 4 _Speed("Speed",Range(1,100)) = 30 } SubShader { Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } LOD 100
Pass { Zwrite off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fog
#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; float _HorAmount; float _VerAmount; float _Speed;
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 { float time = floor(_Time.y * _Speed); float row = floor(time / _HorAmount); float column = time - row * _HorAmount;
half2 uv = i.uv +half2(column,-row); uv.x /= _HorAmount; uv.y /= _VerAmount; fixed4 col = tex2D(_MainTex, uv); UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
|
滚动动画
对uv进行直接的相加
下面的是在顶点着色器中时间的,可以让UV随时间向右变化
1
| o.uv = TRANSFORM_TEX(v.uv, _MainTex) + float2(_ScrollX,0) * _Time.y;
|
顶点动画
最常用的
在顶点着色器中的操作
1
| v.vertex.y = v.vertex.y + _Arange * sin(_Time.y * _Speed + v.vertex.x * _Frequency);
|
广告牌原理
时刻让物体永远朝向摄像机
表面法线,物体中心到摄像机的位置组成的向量
计算方式是将摄像机的坐标从世界空间转换到模型空间,然后用新的相机坐标减去模型的锚点,锚点是模型绕着旋转的点,一般取模型坐标的原点
还有就是在制作组模型的过程中,手动将一个顶点刷上特殊的颜色来作为锚点
三个正交基向量
求解过程是先求出表面法线normal,这个在上文有所提及,
然后求出up法线的近似向量,(0,1,0),这个并不是真正的up向量,只是为了和表面法向量确定一个平面,
然后利用这两个向量cross,叉乘,求出Right,right垂直normal和up组成的平面,
最后normal和right再cross,求出up
代码
顶点着色器中的修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| float3 center = float3(0, 0, 0); float3 view = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
float3 normalDir = view - center; normalDir.y = normalDir.y * _Verical; normalDir = normalize(normalDir);
float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0); float3 rightDir = normalize(cross(upDir, normalDir)); upDir = normalize(cross(normalDir, rightDir));
float3 centerOffs = v.vertex.xyz - center; float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;
o.vertex = UnityObjectToClipPos(float4(localPos,1));
|
改行将三个正交基向量确定的坐标系的Y走锁定在(0,1,0)上,最后的结果是绕Y轴追踪摄像机
对于Quad好用,但是对于Plane,勾选后会导致整个面片消失
1
| normalDir.y = normalDir.y * _Verical;
|