水流的模拟主要运用了顶点变换和纹理动画的结合;
顶点变换中,利用正弦函数模拟河流的大致形态,例如波长,振幅等。
纹理动画中,将纹理坐标朝某一方向持续滚动以形成流动的效果。
脚本如下:
代码语言:javascript复制 1 Shader "MyUnlit/ScrollWater"
2 {
3 Properties
4 {
5 _MainTex ("Texture", 2D) = "white" {}
6 _Color("Color Tint",color)=(1,1,1,1)
7 //控制水流波动的幅度,也就是三角函数中的振幅(值域范围)
8 _Magnitude("Distortion Magnitude",float)=0.3
9 //控制周期的长度,值越大,周期越短,频率越高
10 _InvWaveLength("Distortion Inserve Wave Length",float)=1
11 //流动速度,用于纹理变换
12 _Speed("Speed",float)=0.1
13 }
14 SubShader
15 {
16 //顶点动画需要禁用合P处理
17 Tags {"Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="true" "DisableBatching"="True"}
18
19 Pass
20 {
21 //透明度混合:关闭深度写入 设置混合状态 禁用剔除(双面渲染)
22 Tags{"lightmode"="forwardbase"}
23 ZWrite off
24 Blend SrcAlpha OneMinusSrcAlpha
25 Cull off
26
27 CGPROGRAM
28 #pragma vertex vert
29 #pragma fragment frag
30 #pragma multi_compile_fog
31
32 #include "UnityCG.cginc"
33 struct appdata
34 {
35 float4 vertex : POSITION;
36 float2 uv : TEXCOORD0;
37 };
38
39 struct v2f
40 {
41 float2 uv : TEXCOORD0;
42 UNITY_FOG_COORDS(1)
43 float4 vertex : SV_POSITION;
44 };
45
46 sampler2D _MainTex;
47 float4 _MainTex_ST;
48 fixed4 _Color;
49 float _Magnitude;
50 float _InvWaveLength;
51 float _Speed;
52
53 v2f vert (appdata v)
54 {
55 v2f o;
56 float4 offset;
57 //这里的方向可以自己选择,这里选择偏移x方向,其他方向的偏移保持不变
58 offset.yzw = float3(0, 0, 0);
59 //利用正弦函数模拟河流整体的形状,最后乘以振幅
60 offset.x = sin((v.vertex.x v.vertex.y v.vertex.z)*_InvWaveLength)*_Magnitude;
61 o.vertex = UnityObjectToClipPos(v.vertex offset);
62 //对uv进行某一方向的滚动以模拟水流,这里选择v向
63 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
64 o.uv = float2(0.0, _Time.y*_Speed);
65
66 UNITY_TRANSFER_FOG(o,o.vertex);
67 return o;
68 }
69
70 fixed4 frag (v2f i) : SV_Target
71 {
72 fixed4 col = tex2D(_MainTex, i.uv);
73 col.rgb *= _Color.rgb;
74 UNITY_APPLY_FOG(i.fogCoord, col);
75 return col;
76 }
77 ENDCG
78 }
79 }
80 FallBack "Transparent/VertexLit"
81 }
P.S.需要把纹理的导入设置改为Repeat(重复)
效果如下: