(七)时间动画_Time

1.前言

shaderlab中通过_Time可以获取时间变量,然后可以让图像跟随时间动起来。_Time含有x/y/z/w四个值,分别对应时间t/20、t、2t和3t。当然也可以通过 _SinTime和_CosTime来获取时间的正弦或者余弦值,只不过他们的w分量才是准确值,而xyz值则为w值的八分之一、四分之一和二分之一。

2.播放序列帧

之前有涉及到序列帧播放的问题,最开始是通过RawImage/Image组件实现,即在update中或者通过协程实现固定事件间隔去刷新通向。再次提供两种shader来实现,序列帧的图像在一张图上按顺序排列。此处通过增加时间变量可以通过shader实现。

2.1 顶点片元着色器实现

用到了_Time来获取时间行程。

2.2 序列帧播放

Shader "LL/Sequence" {
	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Main Image", 2D) = "white" {}
    	_Horizontal ("Horizontal Count", Float) = 4
    	_Vertical ("Vertical Count", Float) = 4
    	_Speed ("Speed", Float) = 10
	}
	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"
			
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _Horizontal;
			float _Vertical;
			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 deltaCount=floor(_Time.y*_Speed);
				float period=floor(deltaCount/_Horizontal /_Vertical );
				float posCount=deltaCount-period*_Horizontal *_Vertical;
				
				float row=floor(posCount/_Vertical);
				float column=posCount-_Vertical*row;
				half2 uv=half2(i.uv.x/_Vertical+column/_Vertical ,1-row/_Horizontal -i.uv.y/_Vertical);
				
				fixed4 c = tex2D(_MainTex, uv);
				c.rgb *= _Color;
				
				return c;
			}
			
			ENDCG
		}  
	}
	FallBack "Transparent/VertexLit"
}

2.3 表面着色器实现

此方法搬运此处 ,此文通过表面着色器实现,相对来说更简洁。

Shader "Custom/Sequences" {
Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
                    _CellAmount("Cell Amount", float) = 1
            _Speed("Speed", Range(0.0132)) = 12
    }
    SubShader {
        Tags { "RenderType"="Opaque"}
        LOD 200
        
        CGPROGRAM
        #pragma surface surf Lambert
 
        sampler2D _MainTex;
 
        struct Input {
            float2 uv_MainTex;
        };

                    half _CellAmount;
            half _Speed;
 
        void surf (Input IN, inout SurfaceOutput o) {
        fixed2 texUV = IN.uv_MainTex;
            half cellUVX = 1 / _CellAmount;
            half timeVal = ceil(fmod(_Time.y * _Speed, _CellAmount));
            fixed uvx = texUV.x;
            uvx *= cellUVX;
            uvx += timeVal * cellUVX;
            texUV = fixed2(uvx, texUV.y);
            fixed4 c = tex2D (_MainTex, texUV);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
 
        ENDCG
    }
    FallBack "Diffuse"
}


3.滚动背景

曾遇到一个需求,即需要背景滚动播放,当时采用RawImage实时更改UIRect的w值实现,而且涉及到效果叠加时采用多层背景,且有的背景需要带透明通道。而现在通过shader则不用如此繁琐。注意Layer 2的图片不需要的显示的位置透明通道为0,这样在通过lerp(firstLayer, secondLayer, secondLayer.a)计算时可以筛选出相关颜色值。


Shader "LL/ScrollBackground" {
	Properties {
		_MainTex ("Layer 1", 2D) = "white" {}
		_DetailTex ("Layer 2", 2D) = "white" {}
		_ScrollX ("Layer 1 Speed", Float) = 1.0
		_Scroll2X ("Layer 2 Speed", Float) = 1.0
		_Multiplier ("Layer Multiplier", Float) = 1
	}
	SubShader {
		Tags { "RenderType"="Opaque" "Queue"="Geometry"}
		
		Pass { 
			Tags { "LightMode"="ForwardBase" }
			
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			
			sampler2D _MainTex;
			sampler2D _DetailTex;
			float4 _MainTex_ST;
			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);
				
				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);
				
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target {
				fixed4 firstLayer = tex2D(_MainTex, i.uv.xy);
				fixed4 secondLayer = tex2D(_DetailTex, i.uv.zw);
				
				fixed4 c = lerp(firstLayer, secondLayer, secondLayer.a);
				c.rgb *= _Multiplier;
				
				return c;
			}
			
			ENDCG
		}
	}
	FallBack "VertexLit"
}

4.顶点动画

除了更改uv以外还可以更改顶点坐标。当时有一个工业需求,需要动态显示在固有频率下的模态展示。则需要实时根据频率改变模型的形态,且形态时正弦变化的。假设有一根方形横梁,长度方向为x方向,如果只需要y方向正弦运动,则需要根据x方向实时更改y值,如果有更复杂变化则可以更改其他坐标值。但是会存在相互干扰问题。


Shader "LL/Move" {
	Properties {
		_MainTex ("Main Tex", 2D) = "white" {}
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_Magnitude ("振幅", Float) = 1
 		_Frequency ("频率", Float) = 1
 		_Phase ("相位因子", Float) = 10
 		_Speed ("Speed", Float) = 0.5
	}
	SubShader {
		// Need to disable batching because of the vertex animation
		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;
			fixed4 _Color;
			float _Magnitude;
			float _Frequency;
			float _Phase;
			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;
				
				float4 offset;
				offset.xzw = float3(0.0, 0.0, 0.0);
				
				offset.y = sin(_Frequency * _Time.y+v.vertex.x * _Phase ) * _Magnitude;
				o.pos = UnityObjectToClipPos(v.vertex + offset);
				
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv +=  float2(0.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"
}

5.结论

强迫症晚期,没有结论。

posted @ 2020-05-04 17:22  81192  阅读(363)  评论(0编辑  收藏  举报