【Shader】通过Shader实现森林树木随风摆动效果

       大家首先可以想象一下这样的场景:场景中有一大片森林,我想让这片森林的树木有微风轻轻吹拂而缓缓摆动的效果,应该要怎么实现呢?

       A:给每棵树加个动画,让动画来控制摆动

       方案A如果在树木少的情况下还是属于可接受范围的,而且用美术童鞋做的动画来控制树木摆动会显得更真实更生动。不过注意,当是“森林”的时候,这一动起来,CPU估计就吃不消了,若是美术童鞋为了让树木更生动,加的是骨骼动画,那CPU和DrawCall将会爆表!

       B:用代码控制树木位移来实现

       方案B当然不可能是每棵树挂个脚本,那对性能是极大的浪费。若是直接控制整片森林的位移,首先是要把整片森林形成一个整体,然后是用代码每帧循环地去控制位移。虽然能达到摆动,但是动起来会非常的怪异,很难达到理想的效果,大神们可以去尝试一下。

C:使用Unity自带的Tree和WindZone

方案C不失为一个好方法,能够实现很真实的效果。不过使用Unity自带的Tree有很多美术上的限制,而且配置Tree和Wind Zone也是非常麻烦,性能也有一定的消耗。有时候当我们只需要实现简单的摆动功能,就会显得有些得不偿失,性价比不是很高。

D:…

总而言之,方案各式各样,种类繁多,选中最适合自己的那一个才重要。综上所述,要实现符合简单、仿真、高性能的三大条件,通过Shader的帧动画变换UV采样贴图来实现效果,将是一个不错的选择。

简要说一下原理:一个贴图具体如何被映射到模型的表面是根据模型定点的UV值来决定的。假设不修改的话,一个平面的左下角的UV是(0,0),右上角是(1,1)。然后,根据时间计算出当前帧贴图上相应的UV位置,按照这个位置取贴图中取出对应颜色。其实模型顶点本身的UV信息没变,只是把它传递给我们的UV信息进行加工,获取我们想要的位置上的像素。好的,不多说了,直接上代码吧:

Shader "Consume/Leaf Swing"
{
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Pos("Position",Vector) =(0,0,0,0)
		_Direction("Direction",Vector) =(0,0,0,0)
		_TimeScale("TimeScale",float) = 1
		_TimeDelay("TimeDelay",float) = 1
	}
	SubShader
	{
		LOD 100
		Tags
		{
			"RenderType"="Opaque"
			"Queue"="Transparent"
		}

		CGPROGRAM
		#pragma surface surf Lambert vertex:vert alpha

		sampler2D _MainTex;
		fixed4 _Pos;
		fixed4 _Direction;
		half _TimeScale;
		half _TimeDelay;

		struct Input
		{
			half2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o)
		{
			half4 c = tex2D (_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}

		void vert (inout appdata_full v)
		{  
			half dis = distance(v.vertex ,_Pos) ;
			half time = (_Time.y + _TimeDelay) * _TimeScale;
			v.vertex.xyz += dis * (sin(time) * cos(time * 2 / 3) + 1) * _Direction.xyz;	//核心,动态顶点变换
		}

		ENDCG
	}

	FallBack "Transparent/Cutout/VertexLit"
}

从以上代码我们可以进行这几个参数的配置,位移量:_Pos、方向:_Direction、时间尺度:_TimeScale、延迟时间:_TimeDelay。只要森林的所有树木叶子材质统一使用以上Shader,就能做到微风轻摆的效果,赶紧试试吧~


Ricky Yang个人原创,版权所有,转载注明,谢谢。http://blog.csdn.net/yangyy753

你可能感兴趣的:(U3D,Shader)