Shader笔记——6.Shader动画

摘要:
着色器动画在UnityShader_time、_SinTime、_CosTime、unity_DeltaTime和其他内置变量中引入了时间变量。这些变量可用于获取着色器中的运行时间,以实现各种动画效果。纹理动画可用于替换复杂的粒子系统,以模拟各种动画效果。

Shader动画

在Unity Shader中引入时间变量_Time,_SinTime,_CosTime,unity_DeltaTime等内置变量来获取在Shader中获取运行时间,就可以来实现各种动画效果

纹理动画

我们可以使用纹理动画来代替复杂的粒子系统等来模拟各种动画效果。

序列帧动画Image Sequence Animation

最常见的纹理动画之一就是序列帧动画

Shader "Custom/SequenceAnime" {
    Properties{
    _Color ("Color Tint" , Color) = (1,1,1,1)
    _MainTex ("Sequence Image" , 2D) = "white" {}
    _HorizontalAmount ("Horizontal Amount" , Float) = 4
    _VerticalAmount ("Vertical Amount" ,Float) = 4
    _Speed ("Anime Speed" ,Range(1,100)) = 30
    }
    SubShader{
        Tags{
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }
        Pass{
            Tags{"LightMode" = "ForwardBase"}
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            float4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _HorizontalAmount;
            float _VerticalAmount;
            float _Speed;

            struct a2v {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert (a2v v){
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_TARGET{
                //使用_Time.y乘以速度来模拟时间,再用floor()函数来取得整数时间
                float time = floor(_Time.y * _Speed);
                //时间除以_HorizontalAmount,对结果向下取整为当前时间所处行数
                float row = floor(time / _HorizontalAmount);
                //时间除以_HorizontalAmount的余数,为当前时间所处列数
                float column = fmod(time, _HorizontalAmount);

                //纹理坐标的x、y分别除以_HorizontalAmount和_VerticalAmount,得到子关键帧的纹理坐标范围(此时进行采样输出的就是左下角关键帧)
                half2 uv = float2(i.uv.x / _HorizontalAmount , i.uv.y / _VerticalAmount);

                //使用上面计算出的当前列数对上面得到的子关键帧的纹理坐标范围进行偏移,得到当前子关键帧的纹理坐标
                uv.x += column / _HorizontalAmount;
                uv.y -= row / _VerticalAmount;
                //进行采样
                fixed4 c = tex2D (_MainTex ,uv);
                c.rgb *= _Color;
                return c;
            }
            ENDCG
        }
    }
    Fallback "Transparent/VertexLit"
}

示例序列帧:

walking_robot

序列帧动画效果:

sequenceAnime

在导入此类用途的图片资源时,无论是用于纹理贴图还是UI,需要在导入设置中设置其Wrap Mode为Repeat,因为Wrap Mode的设置决定了当纹理坐标超过了[0,1]时纹理如何被平铺

ImportSet

背景循环动画

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/InfiniteScroll" {
    Properties{
        _MainTex ("Main Tex", 2D) = "white"{}
        _DetailTex ("Detail Tex" ,2D) = "white"{}
        _ScrollX ("Mian Tex Speed" , Float) = 1.0
        _Scroll2X ("Detail Tex Speed" , Float ) = 1.0
        _Multiplier ("Layer Multiplier" , Float) = 1.0
    }
    SubShader{
        Tags{"Queue" = "Geometry" "RenderType" = "Opaque"}
        Pass{
            Tags{"LightMode" = "ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _DetailTex;
            float4 _DetailTex_ST;
            float _ScrollX;
            float _Scroll2X;
            float _Multiplier;

            struct a2v{
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f{
                float4 pos : SV_POSITION;
                float4 uv : TEXCOORD0;
            };

            v2f vert (a2v v){
                v2f o;
                o.pos = UnityObjectToClipPos( v.vertex);
                //通过TRANSFORM_TEX得到转换后的纹理坐标,对其x方向上再进行偏移,且偏移量随时间变量_Time.y而变化
                o.uv.xy = TRANSFORM_TEX(v.texcoord , _MainTex) + float2(frac(_ScrollX * _Time.y),0);
                o.uv.zw = TRANSFORM_TEX(v.texcoord,_DetailTex) + float2(frac(_Scroll2X * _Time.y) ,0);
                return o;
            }

            fixed4 frag (v2f i) : SV_TARGET{
                fixed4 mainLayer = tex2D(_MainTex , i.uv.xy);
                fixed4 detailLayer = tex2D(_DetailTex , i.uv.zw);

                fixed4 c = lerp(mainLayer,detailLayer,detailLayer.a);
                c.rgb *= _Multiplier;
                return c;

            }
            ENDCG
        }
    }
    Fallback "VertexLit"
}

顶点动画

河流流动动画

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/WaterWave"{
    Properties{
        _MainTex ("Main Tex" ,2D) = "white"{}
        _Color ("Color Tint" , Color) = (1,1,1,1)
        _Magnitude ("Distortion Magnitude" , Float) = 1
        _Frequency ("Distortion Frequency" ,Float) = 1
        _InvWaveLength ("Distortion Inverse Wave Length" ,Float) = 1
        _Speed ("Speed" ,Float ) = 1
    }
    SubShader{
        Tags{
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "DisableBatching" = "True"
        }
        Pass{
            Tags{"LightMode" = "ForwardBase"}
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;
            float _Magnitude;
            float _Frequency;
            float _InvWaveLength;
            float _Speed;

            struct a2v{
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert(a2v v){
                v2f o;

                float4 offset;
                offset.yzw = float3(0,0,0);
                offset.x = sin(_Frequency * _Time.y + v.vertex * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength ) * _Magnitude;

                o.pos = UnityObjectToClipPos(v.vertex + offset);
                o.uv = TRANSFORM_TEX(v.texcoord , _MainTex);
                o.uv += float2(0,_Time.y * _Speed);
                return o;
            }

            fixed4 frag(v2f i) :SV_TARGET{
                fixed4 c = tex2D(_MainTex ,i.uv);
                c.rgb *= _Color.rgb;
                return c;
            }
            ENDCG
        }
    }
    Fallback "Transparent/VertexLit"
}

广告牌BillBoard

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'


Shader "Custom/BillBoard"{
    Properties{
        _MainTex ("Main Tex" ,2D) = "white"{}
        _Color ("Color Tint", Color) = (1,1,1,1)
        _VerticalRestraints ("Vertical Restraints", Float) = 1
    }
    SubShader{
        Tags{
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "DisableBatching" = "True"
        }

        Pass{
            Tags{"LightMode" = "ForwardBase"}

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;
            float _VerticalRestraints;

            struct a2v{
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };
            struct v2f{
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert (a2v v){
                v2f o;
                //模型空间中心
                float3 centerPos = float3(0,0,0);
                //摄像机在模型空间中的位置
                float3 viewerPos = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));
                //要使广告牌一直面对摄像机,即广告牌的法线方向一直为摄像机的方向
                float3 normalDir = viewerPos - centerPos;

                normalDir.y = normalDir.y * _VerticalRestraints;
                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 - centerPos;
                //由模型空间坐标原点、新的坐标轴矢量以及各轴偏移量得到此时顶点的位置坐标
                float3 localPos = centerPos + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z ;

                o.pos = UnityObjectToClipPos(float4(localPos,1));
                o.uv = TRANSFORM_TEX(v.texcoord , _MainTex);
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET{
                fixed4 c = tex2D(_MainTex,i.uv);
                c.rgb *= _Color.rgb;
                return c;
            }
            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

REF

文档:

https://docs.unity3d.com/Manual/class-RenderTexture.html

书籍:

OpenGL宝典、Unity Shader入门

免责声明:文章转载自《Shader笔记——6.Shader动画》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇EL表达式获取数据[Golang] go list命令查看依赖的版本下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

unity shader序列帧动画代码,顺便吐槽一下unity shader系统

一、看到UNITY论坛里有些人求unity shader序列帧动画,写shader我擅长啊,就顺势写了个CG的shader。代码很简单,就是变换UV采样序列帧贴图,美术配置行数列数以及变换速度。Shader "HELLOHUAN/Hello_Sequence" { Properties { _Color ("Main Color", Colo...

移动端动画lottie 和 svga的区别

Lottie  只需要 ui设计师给到json动画文件,像img图片一样import引入即可,对应属性   链接:https://juejin.cn/post/6844903661760413704  或者去官网查看 http://airbnb.io/lottie/#/  svga上来需要先播放动画的dom存在,动态的dom不太适合,官网链接 :htt...

cocostudio使用plist创建序列帧动画图片名称序列错乱的问题

cocostudio 版本v2.2.9 用texturePacker将动画帧打包成一个plist和一张png,将plist拖入cocostudio中的资源栏中。 如图所示,plist里面的图片顺序是乱掉的,而且该顺序无法调整,10,11应该在最后,这样选择这11张图创建的序列帧动画中间2帧将是错乱的 如果自己手动调整关键帧很麻烦,那么解决问题的地方就在于...

Unity3D特效-场景淡入淡出

        最近公司开始搞Unity3D..整个游戏..特效需求还是比较多的.关于UI部分的特效淡入淡出.看网上用的方法都是用个黑东东遮挡然后设置alpha这么搞....本大神感觉非常的low.而且很渣.故奋笔疾书借此文鄙视那些low方式. 关于这种处理用shader配合Material非常简单的.先来介绍下使用了哪些东东. 1.肯定是需要一个脚本的....

css动画延迟好像有点怪

项目中需要使用到动画animate.css,在自定义的时候发现设置animation-delay 和 animation-duration 的总时间不对会导致 动画缺失。比如 bounceInLeft 动画 是从左边出现然后 抖动一下 ,当初始animation-delay为0,animation-duration为1s,动画完整,但是如果设置,anima...

过渡(transition) 动画(animation)

过渡(transition) 1.transition   -通过过渡可以指定一个属性发生变化时的切换效果,通过过渡可以创建一些好的效果,提升用户体验。   -可以同时设置过渡相关的所有属性,只有一个要求,如果要写延迟,则俩个时间中第一个是持续时间,第二个是延迟时间。 2.transition-property(指定要执行过渡的属性)   -多个属性间用“...