当前位置:   article > 正文

Unity Shader : _Time实例_unity shader _time

unity shader _time

在日常shader的开发中,经常碰到需要实现动态的shader效果,而unity中提供了_Time变量来供开发者使用 

_Time 是用来驱动shader内部的动画的变量。我们可以用它来计算时间的变换。基于此可以在shader中实现各种动画效果。
官方提供了下面几个变量供我们使用

  1. //t是自该场景加载开始所经过的时间,4个分量分别是 (t/20, t, t*2, t*3)
  2. _Time float4 time (t/20, t, t*2, t*3),
  3. //t 是时间的正弦值,4个分量分别是 (t/8, t/4, t/2, t)
  4. _SinTime float4 Sine of time: (t/8, t/4, t/2, t).
  5. //t 是时间的余弦值,4个分量分别是 (t/8, t/4, t/2, t)
  6. _CosTime float4 Cosine of time: (t/8, t/4, t/2, t).
  7. //dt 是时间增量,4个分量的值分别是(dt, 1/dt, smoothDt, 1/smoothDt)
  8. 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坐标随时间变化,这样可以实现物体形态左右变化及移动的效果

  1. Shader "Unlit/Test_14"
  2. {
  3.     Properties
  4.     {
  5.         _MainTex ("Texture", 2D) = "red" {}
  6.         _CutOutThresh("CutOutThresh",Range(0.0,1.0)) = 0.5
  7.         _Color("Color",Color) = (1,1,1,1)
  8.         _Distance("Distance",float) = 1
  9.         _Speed("Speed",float) = 1
  10.     }
  11.     SubShader
  12.     {
  13.         Tags { "RenderType"="Opaque" }
  14.         LOD 100
  15.         Pass
  16.         {
  17.             CGPROGRAM
  18.             #pragma vertex vert
  19.             #pragma fragment frag
  20.             
  21.             #include "UnityCG.cginc"
  22.             struct appdata
  23.             {
  24.                 float4 vertex : POSITION;
  25.                 float2 uv : TEXCOORD0;
  26.             };
  27.             struct v2f
  28.             {
  29.                 float2 uv : TEXCOORD0;
  30.                 float4 vertex : SV_POSITION;
  31.             };
  32.             sampler2D _MainTex;
  33.             float4 _MainTex_ST;
  34.             float _CutOutThresh;
  35.             float4 _Color;
  36.             float _Distance;
  37.             float _Speed;
  38.             v2f vert (appdata v)
  39.             {
  40.                 v2f o;
  41.                 v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * 0.5) * _Speed;
  42.                 o.vertex = UnityObjectToClipPos(v.vertex);
  43.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  44.                 return o;
  45.             }
  46.             
  47.             fixed4 frag (v2f i) : SV_Target
  48.             {
  49.                 // sample the texture
  50.                 fixed4 col = tex2D(_MainTex, i.uv) + _Color;
  51.                 clip(col.r - _CutOutThresh);
  52.                 return col;
  53.             }
  54.             ENDCG
  55.         }
  56.     }
  57. }

 

下面的代码实现了Sphere的定点 y值 依赖于 x的坐标随时间变化,这样可以实现类似波浪的效果

  1. Shader "Unlit/Test_16"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", 2D) = "red" {}
  6. }
  7. SubShader
  8. {
  9. Tags { "RenderType"="Opaque" }
  10. LOD 100
  11. Pass
  12. {
  13. CGPROGRAM
  14. #pragma vertex vert
  15. #pragma fragment frag
  16. #include "UnityCG.cginc"
  17. struct appdata
  18. {
  19. float4 vertex : POSITION;
  20. float2 uv : TEXCOORD0;
  21. };
  22. struct v2f
  23. {
  24. float2 uv : TEXCOORD0;
  25. float4 vertex : SV_POSITION;
  26. };
  27. sampler2D _MainTex;
  28. float4 _MainTex_ST;
  29. v2f vert (appdata v)
  30. {
  31. v2f o;
  32. v.vertex.y = sin(v.vertex.x + _Time.y); //+=为3Dobject,直接=为2Dobject
  33. o.vertex = UnityObjectToClipPos(v.vertex);
  34. o.uv = v.uv;
  35. return o;
  36. }
  37. fixed4 frag (v2f i) : SV_Target
  38. {
  39. // sample the texture
  40. fixed4 col = tex2D(_MainTex, i.uv);
  41. return col;
  42. }
  43. ENDCG
  44. }
  45. }
  46. }

 

下面的代码实现了Cylinder的棋盘格颜色坐标和背景贴图随时间变化,这样可以实现动态贴图动画和动态棋盘格的效果

  1. Shader "Unlit/Test_8"
  2. {
  3.     Properties
  4.     {
  5.         _Density("Density", Range(2,50)) = 30  // 控制密集程度
  6.         _AnotherTex("AnotherTex",2D) = "white"{}
  7.         _MainTex("Texture", 2D) = "white" {}
  8.     }
  9.     SubShader
  10.     {
  11.         Tags { "RenderType"="Opaque" }
  12.         LOD 100
  13.         Pass
  14.         {
  15.             CGPROGRAM
  16.             #pragma vertex vert
  17.             #pragma fragment frag
  18.             // make fog work
  19.             
  20.             #include "UnityCG.cginc"
  21.             float _Density;   
  22.             sampler2D _AnotherTex;
  23.             sampler2D _MainTex;      
  24.             //声明最好在其通道内方法函数最前面声明,不然获取不到
  25.             struct v2f
  26.             {
  27.                 float2 uv : TEXCOORD0;
  28.                 float4 vertex : SV_POSITION;
  29.             };
  30.             
  31.             
  32.             v2f vert(float4 pos : POSITION, float2 uv : TEXCOORD0)
  33.             {
  34.                 v2f o;
  35.                 o.vertex = UnityObjectToClipPos(pos);
  36.                 o.uv = uv * _Density; //网格uv与面积相乘
  37.                 return o;
  38.             }
  39.             
  40.             fixed4 frag (v2f i) : SV_Target
  41.             {
  42.                 float2 uvOffset = float2(0,0);
  43.                 uvOffset.x = _Time.y * 1;
  44.                 uvOffset.y = _Time.y * 1;
  45.                 fixed4 another_color = tex2D(_AnotherTex, i.uv + uvOffset);//通过_Time.y动态改变anothertex的uv坐标实现动态贴图效果
  46.                 float2 c = i.uv;
  47.                 c = floor(c) / _Time.x; //片元着色器使用floor函数获取输入坐标的整数部分,并将其除以_Time.x实现动态坐标
  48.                 float checker = frac(c.x + c.y) * _Time.x;// 函数 frac 来获取小数部分。结果只能是 0.0 或 0.5。然后,我们将它乘以 2 使其为 0.0 或 1.0,并输出为颜色(这分别产生黑色或白色),并将其乘以_Time.x实现动态颜色变化
  49.                 fixed4 col = tex2D(_MainTex, checker) + another_color;
  50.                 return col;
  51.             }
  52.             ENDCG
  53.         }
  54.     }
  55. }

UnityshaderDemo

(视频中可以看到棋盘格的颜色变化和纹理的变化是有规律的) 

下面的代码实现了金鱼的水中光景纹理贴图变化,这样可以实现模拟金鱼在水中时的效果

  1. Shader "Unlit/Test_13"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", 2D) = "white" {}
  6. _SubTex("Texture", 2D) = "white" {} //水中光景纹理贴图
  7. }
  8. SubShader
  9. {
  10. Tags { "RenderType"="Opaque" }
  11. LOD 100
  12. Pass
  13. {
  14. CGPROGRAM
  15. #pragma vertex vert
  16. #pragma fragment frag
  17. #include "UnityCG.cginc"
  18. struct appdata
  19. {
  20. float4 vertex : POSITION;
  21. float2 uv : TEXCOORD0;
  22. };
  23. struct v2f
  24. {
  25. float2 uv : TEXCOORD0;
  26. float4 vertex : SV_POSITION;
  27. };
  28. sampler2D _SubTex;
  29. sampler2D _MainTex;
  30. float4 _MainTex_ST;
  31. v2f vert (appdata v)
  32. {
  33. v2f o;
  34. o.vertex = UnityObjectToClipPos(v.vertex);
  35. o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  36. return o;
  37. }
  38. fixed4 frag (v2f i) : SV_Target
  39. {
  40. float2 uv_offset = float2(0,0);
  41. uv_offset.x = _Time.y * 0.15;
  42. uv_offset.y = _Time.y * 0.15;
  43. fixed4 light_color = tex2D(_SubTex, i.uv + uv_offset);//通过_Time.y动态改变subtex的uv坐标实现动态贴图效果
  44. fixed4 col = tex2D(_MainTex, i.uv) + light_color;//添加赋值给col
  45. return col;
  46. }
  47. ENDCG
  48. }
  49. }
  50. }

UnityShaderDemo

下面的代码实现了Sphere的像素纹理变化,这样可以实现另一种动态棋盘格的效果

  1. Shader "Unlit/Test_11"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", 2D) = "red" {}
  6. }
  7. SubShader
  8. {
  9. Tags { "RenderType"="Opaque" }
  10. LOD 100
  11. Pass
  12. {
  13. CGPROGRAM
  14. #pragma vertex vert
  15. #pragma fragment frag
  16. #include "UnityCG.cginc"
  17. struct appdata
  18. {
  19. float4 vertex : POSITION;
  20. float2 uv : TEXCOORD0;
  21. };
  22. struct v2f
  23. {
  24. float2 uv : TEXCOORD0;
  25. };
  26. sampler2D _MainTex;
  27. float4 _MainTex_ST;
  28. v2f vert (float4 vertex : POSITION,
  29. float2 uv : TEXCOORD,
  30. out float4 outpos : SV_POSITION)//裁剪空间位置输出,使用像素位置语义将导致难以让裁剪空间位置 (SV_POSITION) 和 VPOS 处于相同的顶点到片元结构中。因此顶点着色器应将裁剪空间位置输出为单独的“out”变量
  31. {
  32. v2f o;
  33. o.uv = uv;
  34. outpos = UnityObjectToClipPos(vertex);
  35. return o;
  36. }
  37. fixed4 frag (v2f i,UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target //VPOS屏幕空间像素位置语义
  38. {
  39. screenPos.xy = floor(screenPos.xy * _Time.y) * 0.5;//用floor函数求screenPos的整数坐标并同时乘以_Time.y实现动态坐标
  40. float checker = -frac(screenPos.r + screenPos.g);// 函数 frac 来获取小数部分为负,实现一个跳过渲染的4*4像素块的棋盘格形态,并将其乘以_Time.x实现动态变化
  41. clip(checker);//checker值为负,如果checker值为负,则clip HLSL指令停止渲染像素
  42. fixed4 c = tex2D(_MainTex, i.uv);//对于剩下保留的像素读取其纹理进行输入
  43. return c;
  44. }
  45. ENDCG
  46. }
  47. }
  48. }

UnityShaderDemo

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/108226
推荐阅读
相关标签
  

闽ICP备14008679号