赞
踩
在日常shader的开发中,经常碰到需要实现动态的shader效果,而unity中提供了_Time变量来供开发者使用
_Time 是用来驱动shader内部的动画的变量。我们可以用它来计算时间的变换。基于此可以在shader中实现各种动画效果。
官方提供了下面几个变量供我们使用
- //t是自该场景加载开始所经过的时间,4个分量分别是 (t/20, t, t*2, t*3)
- _Time float4 time (t/20, t, t*2, t*3),
- //t 是时间的正弦值,4个分量分别是 (t/8, t/4, t/2, t)
- _SinTime float4 Sine of time: (t/8, t/4, t/2, t).
- //t 是时间的余弦值,4个分量分别是 (t/8, t/4, t/2, t)
- _CosTime float4 Cosine of time: (t/8, t/4, t/2, t).
- //dt 是时间增量,4个分量的值分别是(dt, 1/dt, smoothDt, 1/smoothDt)
- nity_DeltaTime float4 Delta time: (dt, 1/dt, smoothDt, 1/smoothDt).
fixed x= Speed * _Time 等价于 fixed x= Speed * _Time.x;
_Time各个分量的值如下:
_Time.x = time / 20
_Time.y = time
_Time.z = time * 2
_Time.w = time * 3
_SinTime.w 等价于 sin(_Time.y)
下面的代码实现了Sphere的定点x值依赖于y的坐标和物体uv坐标随时间变化,这样可以实现物体形态左右变化及移动的效果
- Shader "Unlit/Test_14"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "red" {}
- _CutOutThresh("CutOutThresh",Range(0.0,1.0)) = 0.5
- _Color("Color",Color) = (1,1,1,1)
- _Distance("Distance",float) = 1
- _Speed("Speed",float) = 1
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _CutOutThresh;
- float4 _Color;
- float _Distance;
- float _Speed;
- v2f vert (appdata v)
- {
- v2f o;
- v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * 0.5) * _Speed;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
- fixed4 frag (v2f i) : SV_Target
- {
- // sample the texture
- fixed4 col = tex2D(_MainTex, i.uv) + _Color;
- clip(col.r - _CutOutThresh);
- return col;
- }
- ENDCG
- }
- }
- }
下面的代码实现了Sphere的定点 y值 依赖于 x的坐标随时间变化,这样可以实现类似波浪的效果
- Shader "Unlit/Test_16"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "red" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2f vert (appdata v)
- {
- v2f o;
- v.vertex.y = sin(v.vertex.x + _Time.y); //+=为3Dobject,直接=为2Dobject
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = v.uv;
- return o;
- }
-
- fixed4 frag (v2f i) : SV_Target
- {
- // sample the texture
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
下面的代码实现了Cylinder的棋盘格颜色坐标和背景贴图随时间变化,这样可以实现动态贴图动画和动态棋盘格的效果
- Shader "Unlit/Test_8"
- {
- Properties
- {
- _Density("Density", Range(2,50)) = 30 // 控制密集程度
- _AnotherTex("AnotherTex",2D) = "white"{}
- _MainTex("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- // make fog work
-
- #include "UnityCG.cginc"
-
- float _Density;
- sampler2D _AnotherTex;
- sampler2D _MainTex;
- //声明最好在其通道内方法函数最前面声明,不然获取不到
-
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
-
-
- v2f vert(float4 pos : POSITION, float2 uv : TEXCOORD0)
- {
- v2f o;
- o.vertex = UnityObjectToClipPos(pos);
- o.uv = uv * _Density; //网格uv与面积相乘
- return o;
- }
-
-
- fixed4 frag (v2f i) : SV_Target
- {
- float2 uvOffset = float2(0,0);
- uvOffset.x = _Time.y * 1;
- uvOffset.y = _Time.y * 1;
- fixed4 another_color = tex2D(_AnotherTex, i.uv + uvOffset);//通过_Time.y动态改变anothertex的uv坐标实现动态贴图效果
- float2 c = i.uv;
- c = floor(c) / _Time.x; //片元着色器使用floor函数获取输入坐标的整数部分,并将其除以_Time.x实现动态坐标
- float checker = frac(c.x + c.y) * _Time.x;// 函数 frac 来获取小数部分。结果只能是 0.0 或 0.5。然后,我们将它乘以 2 使其为 0.0 或 1.0,并输出为颜色(这分别产生黑色或白色),并将其乘以_Time.x实现动态颜色变化
- fixed4 col = tex2D(_MainTex, checker) + another_color;
- return col;
- }
- ENDCG
- }
- }
- }
UnityshaderDemo
(视频中可以看到棋盘格的颜色变化和纹理的变化是有规律的)
下面的代码实现了金鱼的水中光景纹理贴图变化,这样可以实现模拟金鱼在水中时的效果
- Shader "Unlit/Test_13"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- _SubTex("Texture", 2D) = "white" {} //水中光景纹理贴图
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
-
- sampler2D _SubTex;
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2f vert (appdata v)
- {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
-
- fixed4 frag (v2f i) : SV_Target
- {
- float2 uv_offset = float2(0,0);
- uv_offset.x = _Time.y * 0.15;
- uv_offset.y = _Time.y * 0.15;
- fixed4 light_color = tex2D(_SubTex, i.uv + uv_offset);//通过_Time.y动态改变subtex的uv坐标实现动态贴图效果
- fixed4 col = tex2D(_MainTex, i.uv) + light_color;//添加赋值给col
- return col;
- }
- ENDCG
- }
- }
- }
UnityShaderDemo
下面的代码实现了Sphere的像素纹理变化,这样可以实现另一种动态棋盘格的效果
- Shader "Unlit/Test_11"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "red" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
-
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
-
- };
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
-
- v2f vert (float4 vertex : POSITION,
- float2 uv : TEXCOORD,
- out float4 outpos : SV_POSITION)//裁剪空间位置输出,使用像素位置语义将导致难以让裁剪空间位置 (SV_POSITION) 和 VPOS 处于相同的顶点到片元结构中。因此顶点着色器应将裁剪空间位置输出为单独的“out”变量
- {
- v2f o;
- o.uv = uv;
- outpos = UnityObjectToClipPos(vertex);
- return o;
-
- }
-
- fixed4 frag (v2f i,UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target //VPOS屏幕空间像素位置语义
- {
-
- screenPos.xy = floor(screenPos.xy * _Time.y) * 0.5;//用floor函数求screenPos的整数坐标并同时乘以_Time.y实现动态坐标
- float checker = -frac(screenPos.r + screenPos.g);// 函数 frac 来获取小数部分为负,实现一个跳过渲染的4*4像素块的棋盘格形态,并将其乘以_Time.x实现动态变化
- clip(checker);//checker值为负,如果checker值为负,则clip HLSL指令停止渲染像素
- fixed4 c = tex2D(_MainTex, i.uv);//对于剩下保留的像素读取其纹理进行输入
- return c;
- }
- ENDCG
- }
- }
- }
UnityShaderDemo
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。