人物走过的草丛,自动出现被踩踏的效果

来源:互联网 发布:编程从娃娃抓起 编辑:程序博客网 时间:2024/04/29 13:56

其实基本原理就是将主角的位置传进shader的_MainPlayerPos,然后根据顶点和人物的位置进行相减求出方向向量,然后进行一个位置的偏移。
但是这种效果的开销是蛮大的,如果是对一整片草(一个obj)进行传值,并且只是进入一定范围才会进行传值,效果还是可以接受的。不过再怎么也没有美术的动画看起来真实,但是美术的动画不会针对一片草进行动画啦。可以配合在一起用,效果是不错的。


Shader"AnimalClamp/GrassMoveByVertex"   //人物走过的草丛,自动出现被踩踏的效果
{
       Properties
       {
              _MainTex ("Texture", 2D) = "white" {}
              _MainTex_Alpha("(A)", 2D) = "white" {}
              _Brightness("Brightness", range(0, 5)) = 1
              _AlphaCutoff("Alpha Cutoff",range(0, 1)) = 1
              _RefluenceDistance("Refluence Distance",float) = 1           //受影响的上限范围,大于该值等于0,就不再受影响了
              _RefluenceArgs("Refluence Args",range(0,10)) = 0              //影响的参数,即最终的一个范围值的上限
              _BlugeShape("Bluge Shape",float) = 5
              _BlugeScale("Bluge Scale",float) = 5
              _BlugeSquare("Bluge Square",float) = 5                              //影响范围的参数
              [HideInInspector]_MainPlayerPos("Main Player Pos",color) = (1,1,1,0)
       }
       SubShader
       {
              Tags{"Queue"="Transparent""RenderType"="Opaque"}
              Pass
              {
                     ZWrite On
                     Blend SrcAlpha OneMinusSrcAlpha
                     CGPROGRAM
                     #pragmavertex vert
                     #pragmafragment frag
                     #pragmatarget 2.0
                     #include"UnityCG.cginc"
                     structappdata
                     {
                           float4vertex : POSITION;
                           float3normal : NORMAL;
                           float4tangent : TANGENT;
                           float2uv : TEXCOORD0;
                     };
                     structv2f
                     {
                           float4pos : SV_POSITION;
                           float2uv : TEXCOORD0;
                           float3square : TEXCOORD1; //娱乐,写着玩的
                     };
                     float_Brightness;
                     sampler2D_MainTex;
                     sampler2D_MainTex_Alpha;
                     float_AlphaCutoff;
                     float4_MainPlayerPos;
                     float_RefluenceDistance;
                     float_RefluenceArgs;
                     float_BlugeShape;
                     float_BlugeScale;
                     float_BlugeSquare;
                     half4tex2D_ETC1(sampler2Dtex,sampler2Dalpha,half2uv)//3
                     {
                           half4final = tex2D(tex, uv);
                           final.a = min(1, tex2D(alpha, uv).r);
                           returnfinal;
                     }
                     v2f vert (appdata v)
                     {
                           v2f o;                                   
                           o.uv = v.uv;
                           float3objVertex = mul(unity_ObjectToWorld, v.vertex).xyz;//先将顶点转换到世界空间
                           float3vertexVec = objVertex.xyz - _MainPlayerPos.xyz;//pos到顶点的方向向量
                           floatdistance = sqrt(vertexVec.x * vertexVec.x + vertexVec.z * vertexVec.z);//距离因子,只控制了x & z,如果需要可以把 y 写进去                      + vertexVec.y * vertexVec.y
                           float3moveArgs = 1 / distance * _BlugeSquare * vertexVec;    //顶点偏移的参数,没有错的
                           o.square = moveArgs;
                           float3moveOffset = moveArgs;// *objVertex.xyz * normalize(vertexVec);//(abs(distance) > _RefluenceDistance ? 0 :
                           float3offset = pow((abs((frac((o.uv + _Time.g *float2(0.25, 0)).r) - 0.5)) * 2), _BlugeShape) * v.normal * _BlugeScale;//草循坏摆动的经验公式
                           offset += clamp(moveArgs, -1, 1) ;//加上被压的offset,把这个值规定到-1到1,以免显示夸张
                           //这里的offset偏移量是依据复制出来的世界空间的顶点信息做得objVertex,包括空间坐标系转换都是用vertexVec ,而不可以直接用v.vertex,因为如果用v.vertex迭代的话,会出现一定距离的误差,这是一个深坑,不知道为什么的深坑
                           offset = mul(unity_WorldToObject, offset);
                           o.pos = UnityObjectToClipPos(v.vertex + offset);//+ vertexVec * distance 好玩的效果
                           returno;
                     }
                     
                     fixed4 frag (v2f i) : SV_Target
                     {
                           fixed4 col = tex2D_ETC1(_MainTex, _MainTex_Alpha, i.uv) ;
                           col.rgb *= _Brightness;
                           clip(col.a - _AlphaCutoff);
                           returncol *float4(i.square, 1);
                     }
                     ENDCG
              }
       }
       //FallBack "Diffuse" //半透明不要打开,因为FallBack中会绘制阴影
}