Unity Shader入门学习(4):纹理动画与顶点动画

1.序列帧动画

//纹理动画之序列帧动画
//序列帧动画的原理非常简单,它像放电影一样,依次播放一系列关键帧图像,当播放速度达到一定数值时,看起来就是一个连续的动画。
Shader "MyShader/ImageSequenceAnimation"
{
    Properties
    {
        _Color("Color Tint",Color) = (1,1,1,1)
        _MainTex("Image Sequence", 2D) = "white" {}//包含关键帧图像的纹理
        _HorizontalAmount("Horizontal Amount",Float) = 8//纹理水平方向关键帧个数
        _VerticalAmount("Vertical Amount",Float) = 8//竖直方向
        _Speed("Speed",Range(1,150)) = 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 "Lighting.cginc"
 
                fixed4 _Color;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float _HorizontalAmount;
                float _VerticalAmount;
                float _Speed;
 
                struct a2v
                {
                    float4 vertex:POSITION;
                    float2 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);					// floor()取整。CG的函数。用_Time.y和速度属性_Speed相乘得到模拟的时间。
				float row = floor(time / _HorizontalAmount);		// 行索引,随时间变化
				float column = time % _HorizontalAmount;		//余数则是列索引。
		
				 //纹理坐标从上到下,所以是-row。下面两种计算方法.这种容易理解。
				half2 uv = float2(i.uv.x /_HorizontalAmount, i.uv.y / _VerticalAmount);//以关键帧帧图像纹理坐标
				uv.x += column / _HorizontalAmount;//列索引/列数(每行个数)
				uv.y -= row / _VerticalAmount;		//同上
				//简化如下
				//half2 uv = i.uv + half2(column, -row);
				//uv.x /=  _HorizontalAmount;
				//uv.y /= _VerticalAmount;
		
				fixed4 c = tex2D(_MainTex, uv);
				c.rgb *= _Color;
		
				return c;
				
				}

 
                ENDCG
            }
        }
        Fallback "Transparent/VertexLit"
}

2.背景动画

//纹理动画之运动的背景
Shader "MyShader/ImageSequenceAnimation"
{
	Properties {
		_MainTex ("Base Layer (RGB)", 2D) = "white" {}			// 第一层背景(较远背景)
		_DetailTex ("2nd Layer (RGB)", 2D) = "white" {}			// 较近背景
		_ScrollX ("Base layer Scroll Speed", Float) = 1.0		// 第一层背景滚动速度
		_Scroll2X ("2nd layer Scroll Speed", Float) = 0.5		// 第二层速度
		_Multiplier ("Layer Multiplier", Float) = 1				// 纹理亮度
	}

    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 "Lighting.cginc"
 
                sampler2D _MainTex;
                float4 _MainTex_ST;
				sampler2D _DetailTex;
                float4 _DetailTex_ST;
                float _ScrollX;
                float _Scroll2X;
                float _Multiplier;
 
                struct a2v
                {
                    float4 vertex:POSITION;
                    float2 texcoord:TEXCOORD0;
                };
 
                struct v2f
                {
                    float4 pos:SV_POSITION;
                    float4 uv:TEXCOORD0;
                };
 
				v2f vert (a2v v) {
					v2f o;
					o.pos = UnityObjectToClipPos(v.vertex);
	
					// TRANSFORM_TEX 得到初始纹理坐标,加上偏移坐标。frac为获取小数部分的值。
					//o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex) + frac(float2(_ScrollX, 0.0) * _Time.y);
					//o.uv.zw = TRANSFORM_TEX(v.texcoord, _DetailTex) + frac(float2(_Scroll2X, 0.0) * _Time.y);

					o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
					o.uv.zw = TRANSFORM_TEX(v.texcoord, _DetailTex);

					return o;
				}

				fixed4 frag (v2f i) : SV_Target {

					float2 uv1 =i.uv.xy + frac(_ScrollX* _Time.y);//frac函数返回数的小数部分。因为uv值在(0,1)内
					float2 uv2 =i.uv.zw + frac(_Scroll2X * _Time.y);

					fixed4 firstLayer = tex2D(_MainTex, uv1);
					fixed4 secondLayer = tex2D(_DetailTex, uv2);
	
					fixed4 c = lerp(firstLayer, secondLayer, secondLayer.a);
					c.rgb *= _Multiplier;
	
					return c;
				}

 
                ENDCG
            }
        }
        Fallback "Transparent/VertexLit"
}

3.波纹顶点动画

//水流
Shader "Custom/Wave" {
	Properties {
	
		_MainTex("Texture", 2D) = "white"{} //纹理
		_Arange("Amplitute", float) = 1//极值
		_Frequency("Frequency", float) = 2//波动频率
		_Speed("Speed",float) = 0.5//控制纹理移动的速度
 
	}
 
	SubShader
	{
		Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" "DisableBatching" = "True"}
		// "DisableBatching" = "True"是为了防止unity批处理出现问题(顶点动画一般都添加此句)
		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;
			float _Frequency;
			float _Arange;
			float _Speed;
			
			struct a2v
			{
				float4 vertex:POSITION;
				float2 texcoord:TEXCOORD0;
			};
	
			struct v2f
			{
				float4 pos:SV_POSITION;
				float2 uv:TEXCOORD0;
				
			};
 

 
			v2f vert(a2v v)
			{
				v2f o;
				 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				 //o.uv = v.texcoord;在没声明_MainTex_ST时可用

				float timer = _Time.y *_Speed;
				//变化之前做一个波动 y=  Asin(ωx+φ)
				float waver = _Arange*sin(timer + v.vertex.x *_Frequency);// timer随时间变化
				v.vertex.y = v.vertex.y + waver;
				o.pos = UnityObjectToClipPos(v.vertex);



				return o;
			}
 

 
			fixed4 frag(v2f i) :SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				return col;
			}	
 
			ENDCG
		}
	}
 
	FallBack "Diffuse"
}

4.广告牌效果

//广告牌效果指的是,一个二维平面的法线方向始终与视线(摄像机的观察方向)相同.它的本质在于构建旋转矩阵,此时我们可以选择三个基向量来构建此矩阵。
//1.根据当前摄像机的方向确定法线方向(广告牌效果的本质),并归一
//normal=normalize(viewDir);
//2.根据得到的法线方向和初始的向上方向(在本地空间中即为float3(0,1,0))计算向右的方向,并归一化
//right=normalize(cross(up,normal));(使用向量的叉乘计算)
//3.用计算后的向右方向和法线方向重新校正向上的方向,得到精确值
//up'=normalize(cross(right,normal));

//广告牌效果指的是,一个二维平面的法线方向始终与视线(摄像机的观察方向)相同.它的本质在于构建旋转矩阵,此时我们可以选择三个基向量来构建此矩阵。
//1.根据当前摄像机的方向确定法线方向(广告牌效果的本质),并归一
//normal=normalize(viewDir);
//2.根据得到的法线方向和初始的向上方向(在本地空间中即为float3(0,1,0))计算向右的方向,并归一化
//right=normalize(cross(up,normal));(使用向量的叉乘计算)
//3.用计算后的向右方向和法线方向重新校正向上的方向,得到精确值
//up'=normalize(cross(right,normal));


Shader "MyUnlit/Billboarding"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color("Color Tint",color)=(1,1,1,1)
    }

    SubShader
    {
        //对顶点进行变换需禁用合P
        Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "true" "DisableBatching" = "True" }

        Pass
        {
            //透明度混合
            Tags{ "lightmode" = "forwardbase" }
            ZWrite off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull off

            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;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;

            v2f vert (appdata v)
            {
                v2f o;
                //计算模型空间中的视线方向
                float3 objViewDir = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));

                //计算旋转矩阵的各个基向量
                float3 normalDir =normalize(objViewDir);
                float3 upDir =float3(0, 1, 0);
                float3 rightDir = normalize(cross(normalDir, upDir));
                upDir = normalize(cross(normalDir, rightDir));

                //用旋转矩阵对顶点进行偏移
                float3 localPos =rightDir * v.vertex.x + upDir * v.vertex.y + normalDir * v.vertex.z;

                //将偏移之后的值作为新的顶点传递计算
                o.vertex = UnityObjectToClipPos(float4(localPos,1));
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.rgb *= _Color.rgb;
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
    fallback "Transparent/VertexLit"
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值