作者:yangyy753

原文链接:http://www.taidous.com/thread-27579-1-1.html

大家首先可以想象一下这样的场景:场景中有一大片森林,我想让这片森林的树木有微风轻轻吹拂而缓缓摆动的效果,应该要怎么实现呢?
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信息进行加工,获取我们想要的位置上的像素。好的,不多说了,直接上代码吧:

 

[AppleScript] 纯文本查看 复制代码
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