Shader笔记——5.Shader动画

Shader动画

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

纹理动画

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

序列帧动画

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


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{
                float time = floor(_Time.y * _Speed);
                float row = floor(time / _HorizontalAmount);//当前时间所处行数
                float column = time - row * _HorizontalAmount;//当前时间所处列数

                half2 uv = float2(i.uv.x / _HorizontalAmount , i.uv.y / _VerticalAmount);
                uv.x += column / _HorizontalAmount;//确定当前时间所需要在_MainTex上采样的纹理坐标uv.x
                uv.y -= row / _VerticalAmount;//确定当前时间所需要在_MainTex上采样的纹理坐标uv.y
                
                fixed4 c = tex2D (_MainTex ,uv);
                c.rgb *= _Color;
                return c;
            }
            ENDCG
        }
    }
    Fallback "Transparent/VertexLit"
}

背景循环动画


// 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入门

转载于:https://www.cnblogs.com/sylvan/p/11223007.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值