Shader "Debug/debugVertexColor"
{
Properties
{
_ColorMask ("ColorMask", Vector) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform half4 _ColorMask;
struct appdata
{
float4 vertex : POSITION;
fixed4 vertexColor : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 vertexColor : COLOR;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.vertexColor = v.vertexColor;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = i.vertexColor*_ColorMask;
return col;
}
ENDCG
}
}
}
Check each leaf have different vertex color. Then they won't move in same phase.
simple trigger script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwayGrassMove : MonoBehaviour
{
private float remainTime;
public static float TimeDuration = 1.5f;
public static float Strength = 1.5f;
public static float BaseStrength = 0;
public AnimationCurve Curve;
public Material swayGrassMat;
private MeshRenderer render;
private Vector4 Dir;
void Start()
{
render = GetComponent<MeshRenderer>();
}
public void StartMove()
{
remainTime = TimeDuration;
}
void OnTriggerEnter(Collider other)
{
Dir = other.gameObject.transform.right.normalized;
StartMove();
}
// Update is called once per frame
void Update()
{
remainTime = remainTime - Time.deltaTime;
if (remainTime > 0)
{
float val = BaseStrength + Curve.Evaluate(remainTime / TimeDuration) * Strength;
render.material.SetFloat("_str", val);
render.material.SetVector("_waveDir", Dir);
}
}
}
use capsule to trigger the grass movement
Rotate around a certain Aixs seems fine
Shader "Effect/SwayWaveGrass"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_speed("Wave Speed",float) = 1
_str("Strength",float) = 1
_waveDir("Wave Direction",Vector) = (0,0,0,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
///////////////////////////////////////////////////////////////////////
// RotationMatrix
//
// Constructs an arbitrary axis rotation matrix
float3x3 RotationMatrix(float3 vAxis, float fAngle)
{
// compute sin/cos of fAngle
float2 vSinCos;
#ifdef OPENGL
vSinCos.x = sin(fAngle);
vSinCos.y = cos(fAngle);
#else
sincos(fAngle, vSinCos.x, vSinCos.y);
#endif
const float c = vSinCos.y;
const float s = vSinCos.x;
const float t = 1.0 - c;
const float x = vAxis.x;
const float y = vAxis.y;
const float z = vAxis.z;
return float3x3(t * x * x + c, t * x * y - s * z, t * x * z + s * y,
t * x * y + s * z, t * y * y + c, t * y * z - s * x,
t * x * z - s * y, t * y * z + s * x, t * z * z + c);
}
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
fixed4 vertexColor : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half _str;
half _speed;
half4 _waveDir;
v2f vert (appdata v)
{
v2f o;
//--per leaf moving---//
half param = sin((_Time.z+v.vertexColor.r*2)*_speed)*v.vertexColor.g*_str;
//float3 aix = cross(v.normal,float3(0,1,0));
//v.vertex.xyz = mul(RotationMatrix(aix,param),v.vertex.xyz);
//--whole grass moving--//
float3 aix = cross(float3(_waveDir.x,0,_waveDir.z),float3(0,1,0));
v.vertex.xyz = mul(RotationMatrix(aix,param),v.vertex.xyz);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);;
return col;
}
ENDCG
}
}
}
Just sin wave less calculation but tend to deform too much
Shader "Effect/WaveGrass"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_speed("Wave Speed",float) = 1
_str("Strength",float) = 1
_waveDir("Wave Direction",Vector) = (0,0,0,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
fixed4 vertexColor : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half _str;
half _speed;
half _duration;
half4 _waveDir;
v2f vert (appdata v)
{
v2f o;
half param = (_Time.z+v.vertexColor.r*2)*_speed;
half param2 = v.vertexColor.g*_str/10;
_waveDir.x = _waveDir.x*sin(param)*param2;
_waveDir.z = _waveDir.z*sin(param)*param2;
v.vertex.x = v.vertex.x+_waveDir.x;
v.vertex.z = v.vertex.z+_waveDir.z;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);;
return col;
}
ENDCG
}
}
}
Just a test project. If unity internal collision is not sufficient, Replace it with your own.