UnityShader学习笔记(二) 让贴图纹理动起来(河流瀑布特效、精灵序列帧实现)

发表于2017-01-22
评论0 4.2k浏览
  大家好,我是Zander。这一章我们将使用纹理贴图实现动画、混合和真实特效来达到理想的效果。
  纹理贴图可以使我们的着色器快速的实现逼真的效果,但是如果添加的纹理贴图过多,会非常影响游戏性能,特别是在移动设备上,需要将纹理贴图的数目降到最小,这样才能使应用程序加载更快,运行起来更加流畅。
  下面带着大家用图片来实现一个河流的效果:


  首先创建一个材质和一个新的着色器文件。为着色器添加属性如下:
1
2
3
4
5
6
Properties {
                _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _ScrollXSpeed ("X Scroll Speed",Range(0,10)) = 2
                _ScrollYSpeed ("Y Scroll Speed",Range(0,10)) = 2
        }
  然后在SubShader中修改CGPROGRAM部分的CG属性,添加变量便于访问
1
2
3
4
fixed4  _MianTint;
               fixed   _ScrollXSpeed;
               fixed   _ScrollYSpeed;
               sampler2D _MainTex;
  修改surf()函数,通过tex2D()函数来改变UV坐标,然后使用内置的_Time变量来实现动态纹理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void surf (Input IN, inout SurfaceOutputStandard o)
                {
                    //创建一个变量 存储图片UV
                    fixed2 scrolledUV  = IN.uv_MainTex;
  
                        //创建临时变量存储 X Y
                        fixed xScrollValue  = _ScrollXSpeed * _Time;
                        fixed yScrollValue  = _ScrollYSpeed * _Time;
  
                        //计算X Y 的偏移
                        scrolledUV += fixed2(xScrollValue,yScrollValue);
  
                        half4 c = tex2D(_MainTex,scrolledUV);
                        o.Albedo = c.rgb;
                        o.Alpha = c.a;
                }
  所用的贴图


  运行Unity,就可以看到河流的效果了
  全部代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Shader "Custom/TexSurfaceShader" {
        Properties {
                _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _ScrollXSpeed ("X Scroll Speed",Range(0,10)) = 2
                _ScrollYSpeed ("Y Scroll Speed",Range(0,10)) = 2
        }
        SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200
                  
                CGPROGRAM
                // Physically based Standard lighting model, and enable shadows on all light types
                #pragma surface surf Standard fullforwardshadows
  
                // Use shader model 3.0 target, to get nicer looking lighting
                #pragma target 3.0
  
                fixed4  _MianTint;
                fixed   _ScrollXSpeed;
                fixed   _ScrollYSpeed;
                sampler2D _MainTex;
  
                struct Input {
                        float2 uv_MainTex;
                };
  
                void surf (Input IN, inout SurfaceOutputStandard o)
                {
                    //创建一个变量 存储图片UV
                    fixed2 scrolledUV  = IN.uv_MainTex;
  
                        //创建临时变量存储 X Y
                        fixed xScrollValue  = _ScrollXSpeed * _Time;
                        fixed yScrollValue  = _ScrollYSpeed * _Time;
  
                        //计算X Y 的偏移
                        scrolledUV += fixed2(xScrollValue,yScrollValue);
  
                        half4 c = tex2D(_MainTex,scrolledUV);
                        o.Albedo = c.rgb;
                        o.Alpha = c.a;
                }
                ENDCG
        }
        FallBack "Diffuse"
}
  接下来 我们来进一步扩展 。来实现一个类似于2D序列帧动画的效果。


  首先准备一张序列帧的图,


  创建一个新的材质 和一个shader,
  在新的着色器中添加属性:
1
2
3
4
5
6
Properties {
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _TexWidth("Sheet Width",float)=0.0
                _CellAmout("Cell Amount",float) = 0.0
                _Speed("Speed",Range(0.01,32)) = 12
        }
  修改Surf()函数里面的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void surf (Input IN, inout SurfaceOutputStandard o)
                {
                    float2 spriteUV  = IN.uv_MainTex; //将输入的UV值存储到临时变量
  
                        float cellPixelWidth  = _TexWidth/_CellAmout; //得到每个精灵的宽度
                        float cellUVPercentage = cellPixelWidth/_TexWidth ;  //计算每个精灵在整张图中的百分比
  
                        float timeVal = fmod(_Time.y *_Speed , _CellAmout);
                        timeVal  = ceil(timeVal);
  
                        float xValue  = spriteUV.x;
  
                        //计算精灵在X方向上UV偏移量
                        xValue += cellUVPercentage * timeVal * _CellAmout; 
                        xValue *= cellUVPercentage;
  
                        spriteUV = float2(xValue,spriteUV.y);
                        // Albedo comes from a texture tinted by color
                        fixed4 c = tex2D (_MainTex, spriteUV) ;
                        o.Albedo = c.rgb;
                  
                        o.Alpha = c.a;
                }
  里面用到的两个数学函数:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Shader "Custom/SpriteAnimationShader" {
        Properties {
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _TexWidth("Sheet Width",float)=0.0
                _CellAmout("Cell Amount",float) = 0.0
                _Speed("Speed",Range(0.01,32)) = 12
        }
        SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200
                  
                CGPROGRAM
                // Physically based Standard lighting model, and enable shadows on all light types
                #pragma surface surf Standard fullforwardshadows
  
                // Use shader model 3.0 target, to get nicer looking lighting
                #pragma target 3.0
  
  
                sampler2D _MainTex;
                fixed  _TexWidth;
                fixed   _CellAmout;
                fixed   _Speed;
  
  
                struct Input {
                        float2 uv_MainTex;
                };
  
  
  
                void surf (Input IN, inout SurfaceOutputStandard o)
                {
                    float2 spriteUV  = IN.uv_MainTex; //将输入的UV值存储到临时变量
  
                        float cellPixelWidth  = _TexWidth/_CellAmout; //得到每个精灵的宽度
                        float cellUVPercentage = cellPixelWidth/_TexWidth ;  //计算每个精灵在整张图中的百分比
  
                        float timeVal = fmod(_Time.y *_Speed , _CellAmout);
                        timeVal  = ceil(timeVal);
  
                        float xValue  = spriteUV.x;
  
                        //计算精灵在X方向上UV偏移量
                        xValue += cellUVPercentage * timeVal * _CellAmout; 
                        xValue *= cellUVPercentage;
  
                        spriteUV = float2(xValue,spriteUV.y);
                        // Albedo comes from a texture tinted by color
                        fixed4 c = tex2D (_MainTex, spriteUV) ;
                        o.Albedo = c.rgb;
                  
                        o.Alpha = c.a;
                }
                ENDCG
        }
        FallBack "Diffuse"
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引