一般我们用短草丛被角色经过或平常的飘动效果都是用3d实现的,3d实现起来就比较简单,就是对模型上的顶点做与角色距离的相反方向偏移就好了,平常的飘动效果一般是用sin做弧度变化或者甚至就直接uv的来回移动就好。
我们是3渲2的画面俯四十五度固定视角的游戏,因为2d就一个面片,所有顶点都在一个面片上,如果一个面片上的点往3d的四周扩散,会让这个效果显得很2d。
在这里的话我采取了另一种实现方式,因为从踩短草丛的效果上看,一般是
1.草往斜前方偏移或者往后前方偏移的(找不到图演示)
2.草完全被人踩在脚底的。
草完全被踩在脚底就相当于不显示了,这一块我的做法其实和前面做法是一样的。
首先确定的是我们的游戏是俯四十五度固定视角,是固定的。所以我们就可以思考下这个视角的特点。这个视角要操作的是正面的草,不能操作侧面的草。所以我们要做偏移可以往三个方向做“固定”的偏移。
首先要调整法向量:
xy方向是要一起移动的,不然只移动x方向或只移动y方向都看不到效果。因为希望的是他变形之后是呈现梯形变化的,所以也就需要底部小,顶部大。
顶点的法向量需要调整一下,主要是法向的y需要调低,法向量的x轴则需要根据角色位置点与顶点的距离,如果大则向右,小则向左偏移。
然后调整真正的顶点三个方向的值,x需要根据角色与顶点位置向两边扩散,y需要向下移动,z需要根据位置角色与顶点的位置向前后扩散。
草的飘动效果就比较简单,根据uv的y来确定他飘动的幅度就好,草的根是不动的
// Diablo Lite Shaders - Dave Lindsay
Shader "DiabloLite v2/Grass"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_FakeNrm ("Fake Bump", 2D) = "white" {}
_HighlightPow("Highlight Power", Range(0,4)) = 2
_HighlightAmt("Highlight Strength", Range(0,4)) = 2
_GrassDistance("Grass Distance", Range(0,4)) = 2
_GrassPower("Grass Power", Range(1,3)) = 2
_GrassSway("Grass Sway", Range(0,0.4)) = 0.2
}
Subshader
{
ZWrite Off
//ZTest Off
Fog{ Mode Off }
Lighting Off
Cull Off
Tags { "RenderType"="Transparent" "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#include "Light2DNormalMgr.cginc"
// =========================================================
uniform sampler2D _MainTex;
uniform sampler2D _FakeNrm;
uniform float4 _MainTex_ST;
uniform float _GrassDistance;
uniform float _GrassPower;
uniform float _GrassSway;
uniform half _HighlightAmt;
uniform half _HighlightPow;
uniform float3 _GrassPos;
uniform float3 _LightPos;
uniform float4 _LightColor;
uniform float4 _ShadeColor;
uniform float _LightRangeMin;
uniform float _LightRangeMax;
uniform float _LightRangeNormal;
uniform float _GrassHandlerDistance;
uniform float _GrassVerticalPow;
uniform float _GrassTransversePow;
// =========================================================
struct v2f
{
float4 pos : SV_POSITION;
float2 texture_uv : TEXCOORD0;
float3 light_dir : TEXCOORD1;
float light_dst : TEXCOORD2;
float3 worldPos : TEXCOORD3;
};
// =========================================================
v2f vert (appdata_full v)
{
v2f o;
o.texture_uv = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 tempWorldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
tempWorldPos.z += 0.5;
half dis = distance(_LightPos, tempWorldPos);
dis = dis >= _GrassHandlerDistance ? 0 : (_GrassHandlerDistance - dis);
v.normal.y -= dis;
v.normal.x += (tempWorldPos.x - _LightPos.x) * _GrassTransversePow;
v.vertex.xy += dis * (v.normal.xy * _GrassVerticalPow * o.texture_uv.y);
v.vertex.z += (tempWorldPos.z - _LightPos.z) * dis;//
float bending;
float bend_coef = 10 * (tempWorldPos.x + tempWorldPos.z);
bending = sin(bend_coef + _Time.z) * _GrassSway;
float3 grass_dir = normalize(_GrassPos - tempWorldPos);
bending += grass_dir.x * max(0, _GrassDistance - pow(distance(_GrassPos.xz, tempWorldPos.xz), _GrassPower));
bending *= v.color.a;
v.vertex.x -= bending * o.texture_uv.y;
o.pos = UnityObjectToClipPos(v.vertex);
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.worldPos = worldPos;
return o;
}
// =========================================================
fixed4 frag (v2f i) : COLOR
{
fixed4 colortex = tex2D(_MainTex, i.texture_uv);
fixed4 outcolor = colortex;
half2 normalUV = i.texture_uv;
outcolor.rgb = Light2DHandler(colortex, _LightColor, _ShadeColor, _FakeNrm, normalUV, _HighlightPow, _HighlightAmt, i.worldPos,
_LightPos, _LightRangeMax, _LightRangeMin, _LightRangeNormal);
return outcolor;
}
ENDCG
}
}
}