2d short grass trampling and idle effect

Generally, we use short grass to be passed by the character or the usual floating effect is realized in 3d, which is relatively simple, that is, it's better to offset the vertex on the model in the opposite direction of the character's distance, and the usual floating effect is generally to use sin for arc change or even to move back and forth directly uv.

We are a game in which the screen of 3-2 is 45 degrees down and the angle of view is fixed, because 2d is a patch, and all the vertices are on a patch. If the points on a patch spread around 3d, the effect will be very 2d.


Here, I take another way to realize it, because from the effect of stepping on the grass, it is generally

1. The grass is inclined to move forward or backward to move forward (can't find the illustration)

2. The grass is completely trampled on the foot.


When the grass is completely trampled on the sole of the foot, it is equivalent to not showing. In fact, my way of doing this is the same as the previous way.


First of all, we are sure that our game is 45 degrees fixed perspective, is fixed. So we can think about the characteristics of this perspective. This perspective is to operate the front grass, not the side grass. So we need to make offsets that can be "fixed" in three directions.

First, adjust the normal vector:

The x y direction is to move together, otherwise moving only the x direction or only the y direction will not see the effect. Because what we hope is that after the deformation, it will be trapezoidal, so we need a small bottom and a large top.

The normal vector of the vertex needs to be adjusted. The main reason is that the normal y needs to be lowered. The x axis of the normal vector needs to be adjusted according to the distance between the character's position point and the vertex. If it is large, it needs to be shifted to the right. If it is small, it needs to be shifted to the left.


Then adjust the value of the three vertices of the real vertex. x needs to diffuse to the two sides according to the role and vertex position. y needs to move downwards, and z needs to move back and forth according to the location role and the location of the vertex.


The floating effect of grass is relatively simple. It is good to determine the floating range according to the y of uv. The root of grass is immovable


// Diablo Lite Shaders - Dave Lindsay

Shader "DiabloLite v2/Grass"
_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

ZWrite Off
//ZTest Off
Fog{ Mode Off }
Lighting Off
Cull Off

Tags { "RenderType"="Transparent" "Queue" = "Transparent" }

Blend SrcAlpha OneMinusSrcAlpha

	#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;


Published 59 original articles, won praise, visited 20000+
Private letter follow

Tags: Fragment

Posted on Wed, 11 Mar 2020 00:32:54 -0700 by devarishi