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

2015年08月04日 12:02 0 点赞 0 评论 更新于 2017-05-08 14:30

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

需求背景

大家可以先想象这样一个场景:在游戏或者虚拟环境中有一大片森林,我们希望这片森林中的树木能呈现出被微风轻轻吹拂而缓缓摆动的效果,该如何实现呢?下面为大家分析几种常见的实现方案。

实现方案分析

方案A:给每棵树添加动画

在树木数量较少的情况下,这种方案是可以接受的。使用美术人员制作的动画来控制树木摆动,能够让效果显得更加真实和生动。然而,当场景是一片“森林”时,大量树木同时播放动画会给CPU带来巨大的负担。如果美术人员为了让树木更加生动而使用骨骼动画,CPU的负载和DrawCall(绘制调用)将会急剧增加,可能导致性能严重下降。

方案B:用代码控制树木位移

直接为每棵树挂载脚本控制位移会造成性能的极大浪费。如果直接控制整片森林的位移,需要先将整片森林视为一个整体,然后通过代码在每一帧循环控制其位移。虽然这种方法能够实现摆动效果,但树木动起来会非常怪异,很难达到理想的效果,有兴趣的开发者可以尝试一下。

方案C:使用Unity自带的Tree和WindZone

这是一种能够实现较为真实效果的方法。不过,使用Unity自带的Tree在美术方面存在很多限制,并且配置Tree和Wind Zone的过程非常繁琐,同时也会消耗一定的性能。当我们只需要实现简单的摆动功能时,这种方法的性价比不高,可能会得不偿失。

综合选择

综上所述,实现森林树木摆动效果的方案多种多样,我们需要选择最适合自己的方法。要满足简单、仿真、高性能这三大条件,通过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

作者信息

洞悉

洞悉

共发布了 515 篇文章