• (七)时间动画_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 表面着色器实现

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

    		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;
    		}
    

    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.结论

    强迫症晚期,没有结论。

  • 相关阅读:
    paste 合并文件
    split 分割文件
    cut 从文本中提取一段文字并输出
    tailf 跟踪日志文件
    tail 显示文件内容尾部
    给Linux系统新增加一块硬盘
    Centos7+httpd+fastcgi安装提示错误
    Redhat 7使用CentOS 7的Yum网络源
    windows7下cmd窗口使用ssh命令
    PHP set_error_handler() 函数
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/12827309.html
Copyright © 2020-2023  润新知