UnityShader22:序列帧动画 |
您所在的位置:网站首页 › 定格动画的优势和劣势 › UnityShader22:序列帧动画 |
一、序列帧动画 序列帧动画的原理是如此的简单,可以说只需要足够多张纸以及足够多的时间,就可以实现最简单的动画: 不使用 Animation 工具,只需要使用 Shader 中的内置时间变量,就可以实现最简单的序列帧动画了。就像最早的电影,依次展示一张又一张的图片,只要这些图片是连续的并且切换的足够快,那么当然就可以骗过人的眼睛,得到细腻的动画效果(现在我们的电脑电视本质上依然是这个原理,只不过是以帧的形式表现的)‘ 序列帧的优点和缺点都很明显: 优点:无需任何计算,直接显示图片,逻辑简单,不用怎么考虑性能缺点:制作非常耗时,需要给出 N 张图片,并且为了不占太多的空间往往单张图片分辨率都很低这是《Unity3D入门精要》中的一张例图,64张帧动画图像被合并在一张大的图像中,它们的大小相同,都为128 x 128,这些单张的图像有时也被叫做精灵(Sprite) 这也是 Unity3D 图集的处理方案 二、Unity内置时间变量 对于上面的图片,在 Shader 中只需要按照从左上到右下的顺序,依次截取一个个128 x 128的子区域作为当前要显示的纹理,就可以实现最简单帧序列动画了 在此之前,我们需要在 UnityShader 中获取当前场景运行的时间需要知道以下变量: _Time:float4(t/20, t, 2t, 3t):其中 t 为自当前场景加载开始所经过的时间_SinTime:float4(t/8, t/4, t/2, t):其中 t 为自当前场景加载开始所经过的时间的正弦值_CosTime:float4(t/8, t/4, t/2, t):其中 t 为自当前场景加载开始所经过的时间的正弦值unity_DeltaTime:float(dt, l/dt, smoothDt, 1/smoothDt):其中 dt 为时间增量,smoothDt 为平滑处理后的时间增量三、简单的爆炸效果 直接上代码,主要需要注意的有: 需要当作半透明对象处理,并且对于纹理,需要勾选 Alpha Is Transparency 属性核心在于片段着色器,根据上一节的内置时间变量推算当前应该截取64块区域中的哪一块,并且得出正确的 uv,采样可能结果看上去不是很好,这也是上面所说的缺点:为了保证动画流畅,只能牺牲画质 其实对于这样的火焰效果,一个主流的解决方案是使用粒子特效 四、UV动画 UV 动画就是随时间不断改变纹理的 uv 坐标,以展现出“动态的”贴图 以下 Shader 可以实现滚动背景的效果,在没学 Shader 之前,背景的滚动都是通过修改其 transform 实现的 Shader "Jaihk662/ScrollAni1" { Properties { _MainTex("Base Layer(RGBA)", 2D) = "white" {} _DetailTex("2nd Layer(RGBA)", 2D) = "white" {} _ScrollX("Base layer Scroll Speed", Float) = 1.0 _Scroll2X("2nd layer Scroll Speed", Float) = 1.0 _Multiplier("Layer Multiplier", Float) = 1 } SubShader { LOD 200 Tags { "RenderType" = "Opaque" "Queue" = "Geometry" } PASS { Tags { "LightMode" = "ForwardBase" } ZWrite Off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert //声明顶点着色器的函数 #pragma fragment frag //声明片段着色器的函数 #include "UnityCG.cginc" #include "Lighting.cginc" sampler2D _MainTex; sampler2D _DetailTex; float _ScrollX; float _Scroll2X; float _Multiplier; float4 _MainTex_ST; float4 _DetailTex_ST; struct _2vert { float4 vertex: POSITION; float4 texcoord: TEXCOORD0; }; struct vert2frag { float4 pos: SV_POSITION; float4 uv: TEXCOORD0; }; vert2frag vert(_2vert v) { vert2frag o; o.pos = UnityObjectToClipPos(v.vertex); o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex) + frac(float2(_ScrollX, 0.0) * _Time.y); //frac(): 仅保留小数部分 o.uv.zw = TRANSFORM_TEX(v.texcoord, _DetailTex) + frac(float2(_Scroll2X, 0.0) * _Time.y); return o; } fixed4 frag(vert2frag i): SV_Target { fixed4 firstLayer = tex2D(_MainTex, i.uv.xy); fixed4 secondLayer = tex2D(_DetailTex, i.uv.zw); fixed4 color = lerp(firstLayer, secondLayer, secondLayer.a) * _Multiplier; return color; } ENDCG } } FallBack "VertexLit" }
参考资料: 《UnityShader入门精要》https://opengameart.org/
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |