一、简介
纹理贴图可以使我们的着色器更有生命力,而且可以快速地实现非常逼真的效果。然而略显遗憾的是,你需要小心翼翼地控制用于着色器地纹理贴图的数目,因为如果添加的纹理图片过多,会非常影响游戏的性能。于是我们可以通过修改UV坐标实现纹理贴图的滚动,使用这种技术实现如瀑布,河流,熔岩流等效果
二、准备工作
创建一个新的着色器文件和一个新的材质。这样,我们就创建一个简介漂亮的着色器,我们可以使用它来研究滚动效果。
三、如何操作
首先,打开刚才创建的着色器文件,然后输入下面提到的代码
1.该着色器需要两个新的属性,我们可以用来控制纹理滚动的速度。因此,我们将添加x方向的速度属性和y方向的速度属性,如下代码所示:
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
}
2.修改位于CGPROGRAM部分的CG属性,添加两个新的属性变量便于以后访问
fixed4 _MainTint;
fixed _ScrollXSpeed;
fixed _ScrollYSpeed;
sampler2D _MainTex;
3.修改surf()函数,通过tex2D()函数来改变UV坐标。然后使用内置的_Time变量来实现动态纹理,当我们点击Unity播放按钮时纹理会随时间动起来
void surf (Input IN, inout SurfaceOutput o)
{
fixed2 scrolledUV = IN.uv_MainTex;
fixed xScrollValue = _ScrollXSpeed * _Time;
fixed yScrollValue = _ScrollYSpeed * _Time;
scrolledUV += fixed2(xScrollValue, yScrollValue);
half4 c = tex2D (_MainTex, scrolledUV);
o.Albedo = c.rgb * _MainTint;
o.Alpha = c.a;
}
下图展示了使用滚动UV系统为你的环境创建一个简单河流运动的效果图
四、实现原理
这套纹理滚动系统首先需要声明两个属性,使着色器的使用者能够提高或降低纹理的滚动速度。它的作用在于我们可以从材质Inspector面板中获取浮点值,然后传递给着色器里的surf函数。在程序的开始,我们首先将UV值存储在scrolledUV变量中。这个变量必须是一个float2或fixed2类型的变量,因为UV值是通过Input结构体传入的:
struct Input
{
float2 uv_MainTex;
};
这样,当访问网格的UV时,我们可以使用滚动速度变量和内置的_Time变量对纹理进行便宜。该内置变量返回的是float4类型的值,这意味着当我们进入游戏时,变量的每个组成部分都包含不同的时间值。
_Time变量为我们提供一个基于Unity游戏时钟的递增型浮点值。因此,我们可以使用该事件值在UV方向上移动我们的UV值,也可以通过滚动速度变量来加快或减慢时间。
fixed xScrollValue = _ScrollXSpeed * _Time;
fixed yScrollValue = _ScrollYSpeed * _Time;
scrolledUV += fixed2(xScrollValue, yScrollValue);
half4 c = tex2D (_MainTex, scrolledUV);
五、全部代码
Shader "liulongling/ScrollingUVs" {
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
#pragma surface surf Lambert
fixed4 _MainTint;
fixed _ScrollXSpeed;
fixed _ScrollYSpeed;
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed2 scrolledUV = IN.uv_MainTex;
fixed xScrollValue = _ScrollXSpeed * _Time;
fixed yScrollValue = _ScrollYSpeed * _Time;
scrolledUV += fixed2(xScrollValue, yScrollValue);
half4 c = tex2D (_MainTex, scrolledUV);
o.Albedo = c.rgb * _MainTint;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
本文参考了《Unity Shaders and Effects Cookbook》一书,感谢原书作者提供的学习资料