Shader "URP/Environment/Grass/GrassOriginFly"
{
	Properties
	{
		[HideInInSpector]_Color("Color", Color) = (1,1,1,1)
		[HideInInSpector]_Cutoff("Alpha cutoff", Range(0,1)) = 0.5
		[HideInInSpector]_SpecularPower("Specular Power", Range(0.01, 1)) = 0.078125
		[HideInInSpector]_Gloss("Gloss", Range(0, 4)) = 0.5
		[HideInInSpector]_MainTex("Albedo (RGB)", 2D) = "white" {}
		_BladeHeight("Blade Height",Vector) = (0,0.5,0,0)
		//_SectorWPosInfo("SectorWPosInfo",Vector) = (0,0,0,0)
		//_SectorUVScaleInfo("SectorUVScaleInfo",Vector) = (0 ,0, 0, 0)
		//_SectorMaskSelector("SectorMaskSelector",Vector) = (0, 0, 0, 0)
		//_SectorShadowMaskTex("SectorShadowMaskTex",2D) = "white" {}
		//_ShadowCoef("Shadow Coef", Range(-1, 1)) = 0.3

		[HideInInSpector]_WindIntensity("Wind Intensity", Float) = 0.3

		[Space(4)]
		[Header(Cutoff Grass Animation Settings)]
		[Space(2)]
		[Header(Lifetime)]
		_AnimateTime("animate time", Float) = 0.6
		_AnimateTimeEnd(" ", Float) = 1.6
		[HideInInSpector] _AnimateTimeRand(" ", Float) = 0

		[Space(2)]
		[Header(Grass Density)]
		_Density("grass density", Range(0,1)) = 1

		[Space(2)]
		[Header(Wind Intense)]
		_WindDirX("wind intense in X component", Range(-1,1)) = 0.0
		_WindDirZ("wind intense in Z component", Range(-1,1)) = 0.0

		[Space(2)]
		[Header(Horizontal Velocity)]
		_VelocityInit("horizontal velocity", Float) = 1
		_VelocityInitEnd(" ", Float) = 2
		[HideInInSpector] _VelocityRand(" ", Float) = 1
		_DirRand("direction rand", Float) = 1.5
		//_VelocityRandZ("velocity rand in z", Float) = 1
		_VelocityFinal("final horizontal velocity", FLoat) = 1
		_VelocityDamp("horizontal velocity damp", Range(1,10)) = 5

		[Space(2)]
		[Header(Vertical Velocity)]
		_AriseVelocityInit("vertical velocity", Float) = 0.3
		_AriseVelocityInitEnd(" ", Float) = 0.7
		[HideInInSpector] _AriseVRand(" ", Float) = 0
		_AriseGravity("gravity", Float) = 0.2
		_AriseGravityEnd(" ", Float) = 0.5
		[HideInInSpector] _AriseGRand(" ", Float) = 0

		[Space(2)]
		[Header(Vertical Wave Noise)]
		[HideInInSpector] _AnimateNoiseAmp("vertical wave noise amplitude", Float) = 0.15
		[HideInInSpector] _AnimateNoiseFreq("vertical wave noise freq", Float) = 3

		[Space(2)]
		[Header(Grass Blade Scale)]
		//_InitScale("init grass scale", Range(1,2)) = 1
		_ScaleDamp("缩放衰减", Range(0,1)) = 0.5

		[Space(2)]
		[Header(Rotation Velocity)]
		_RotVelocityInit("rotation velocity", Float) = -1
		_RotVelocityInitEnd(" ", Float) = 3
		[HideInInSpector] _RotRand(" ", Float) = 1
		//_RotVelocityFinal("final rotation veloctiy", Float) = 2
		_RotVelocityDamp("rotation damp", Range(0,10)) = 8

		[Space(2)]
		[Header(Transparent Transition)]
		_TransparentTime("Transparent time percent", Range(0, 1)) = 0.2

		//for satisfy srp shader property requirement
		[HideInInSpector]_SkillforGrassDirectionEncodeTex_TexelSize("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_SkillforGrassTimeEncodeTex_TexelSize("", Vector) = (0, 0, 0, 0)
		//[HideInInSpector]_MainCharPos("", Vector) = (0, 0, 0, 0)
		//[HideInInSpector]_WorldOffset("", Vector) = (0, 0, 0, 0)
		//[HideInInSpector]_TerrainBasePos("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_SkillDirection("", int) = 0

	}
		
	SubShader{
		//Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout_WorldOffset" }
		Tags{ "Queue" = "Transparent" "RenderPipeline" = "LightweightPipeline" "RenderType" = "Transparent" "IgnoreProjector" = "True" }
		Cull Off
		LOD 200

	HLSLINCLUDE
#define SAMPLE_SH_X2MSCENE
#define SHADOW_BAKED_SECTOR
		#define SAMPLE_SH_X2MSCENE
		#define X2M_ENVGI
		#define X2M_GI_BAKED


#include "/Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "/Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "../../Common/Function/Scene_Common.hlsl"
#include "FoliageWindField.hlsl"
#include "FoliageLighting.hlsl"

		TEXTURE2D(_MainTex);							SAMPLER(sampler_MainTex);
		TEXTURE2D(_RampTex);							SAMPLER(sampler_RampTex);
		TEXTURE2D(_SkillforGrassDirectionEncodeTex);	SAMPLER(sampler_SkillforGrassDirectionEncodeTex);
		TEXTURE2D(_SkillforGrassTimeEncodeTex);			SAMPLER(sampler_SkillforGrassTimeEncodeTex);
		TEXTURE2D(_BurnTex);							SAMPLER(sampler_BurnTex);

		CBUFFER_START(UnityPerMaterial)
			float4 _WorldOffset;
			float4 _MainCharPos;
			float4 _SkillforGrassDirectionEncodeTex_TexelSize;
			float4 _SkillforGrassTimeEncodeTex_TexelSize;

			float4 _MainTex_ST;
			float4 _TimeEditor;
			float4 _BladeHeight;

			half4 _Color;
			half4 _GrassRect;

			//for grass animation
			//for grass fly animate direction
			float3 _TerrainBasePos;
			int _SkillDirection;

			//for grass fly settings
			half2 _BurnTex_Scale;
			half _WindDirX;
			half _WindDirZ;
			half _WindIntensity;

			half _VelocityInit;
			half _VelocityInitEnd;
			half _VelocityRand;// = _VelocityInitEnd - _VelocityInit;
			half _DirRand;
			half _VelocityFinal;
			half _VelocityDamp;

			half _AnimateNoiseAmp;
			half _AnimateNoiseFreq;

			half _AnimateTime;
			half _AnimateTimeEnd;
			half _AnimateTimeRand;// = _AnimateTimeEnd - _AnimateTime;

			half _Density;

			half _AriseGravity;
			half _AriseGravityEnd;
			half _AriseGRand;// = _AriseGravityEnd - _AriseGravity;

			half _AriseVelocityInit;
			half _AriseVelocityInitEnd;
			half _AriseVRand;// = _AriseVelocityInitEnd - _AriseVelocityInit;
			half _ScaleDamp;

			half _RotVelocityInit;
			half _RotVelocityInitEnd;
			half _RotVelocityDamp;
			half _RotRand;// = _RotVelocityInitEnd - _RotVelocityInit;

			half _TransparentTime;
			//end grass animation

			half _Cutoff;
			half _TexScaleX;
			half _SpecularPower;
			
			//half _ShadowCoef;
			half _Gloss;

		CBUFFER_END

        uniform half3 _ColorTop, _CMaskTop, _CMaskTopG, _Flip_CMaskTopG, _ColorHL;
        uniform half3 _ColorBottom, _CMaskBottom, _CMaskBottomG, _Flip_CMaskBottomG;
        uniform half _GradientS;

	float3 CalRunWindPos(float3 posWorld, float grassHeight, float intense)
	{
		float3 wind_sensitivity = GetGlobalWindValue(posWorld) * _WindIntensity * grassHeight * intense;
		//wind_sensitivity = mul(unity_ObjectToWorld, float4(wind_sensitivity.xyz, 0.0));
		return posWorld.xyz + wind_sensitivity.xyz;
	}

	half4 GetSkillforGrassDirectionEncode(float3 worldPos)
	{
		half4 ret = half4(0, 0, 0, 0);
		float2 uv = floor(worldPos.xz * 5) - floor(_MainCharPos.xz * 5);
		uv *= _SkillforGrassDirectionEncodeTex_TexelSize.xy;
		uv += float2(0.5, 0.5);

#if UNITY_UV_STARTS_AT_TOP
		// DX
		uv.y = 1.0 - uv.y;
		// OpenGL, don't need 1.0 - y
#endif

		if (uv.x >= 0 && uv.x <= 1 && uv.y >= 0 && uv.y <= 1)
		{
			ret = SAMPLE_TEXTURE2D_LOD(_SkillforGrassDirectionEncodeTex, sampler_SkillforGrassDirectionEncodeTex, uv, 0);
		}

		return ret;
	}

	half4 GetSkillforGrassTimeEncode(float3 worldPos)
	{
		half4 ret = half4(0, 0, 0, 0);
		float2 uv = floor(worldPos.xz * 5) - floor(_MainCharPos.xz * 5);
		uv *= _SkillforGrassTimeEncodeTex_TexelSize.xy;
		uv += float2(0.5, 0.5);

#if UNITY_UV_STARTS_AT_TOP
		// DX
		uv.y = 1.0 - uv.y;
		// OpenGL, don't need 1.0 - y
#endif
		if (uv.x >= 0 && uv.x <= 1 && uv.y >= 0 && uv.y <= 1)
		{
			ret = SAMPLE_TEXTURE2D_LOD(_SkillforGrassTimeEncodeTex, sampler_SkillforGrassTimeEncodeTex, uv, 0);
		}

		return ret;
	}

	bool ReduceDensity(half density, half key)
	{
		if (key > density)
			return true;
		else
			return false;
	}

	//Goldman fomula
	float3 RotateAboutAxis(float angle, half3 axis, float3 verts) {
		float3 rotVert;
		float cosA = cos(angle);
		float sinA = sin(angle);
		float one_cosA = 1 - cosA;
		float azs = axis.z*sinA;
		//half ays = axis.y*sinA;
		//half ays = 0;
		float axs = axis.x*sinA;
		//half axay1_c = axis.x*axis.y*one_cosA;
		//half axay1_c = 0;
		float axaz1_c = axis.x*axis.z*one_cosA;
		//half ayaz1_c = axis.y*axis.z*one_cosA;
		//half ayaz1_c = 0;
		float axax1_cpc = axis.x*axis.x*one_cosA + cosA;
		//half ayay1_cpc =  axis.y*axis.y*one_cosA + cosA;
		float ayay1_cpc = cosA;
		float azaz1_cpc = axis.z*axis.z*one_cosA + cosA;

		//float3x3 rotMatrix = float3x3(
		//	axax1_cpc, axay1_c - azs, axaz1_c + ays,
		//	axay1_c + azs, ayay1_cpc, ayaz1_c - axs,
		//	axaz1_c - ays, ayaz1_c + axs, azaz1_cpc
		//	);
		float3x3 rotMatrix = float3x3(
			axax1_cpc, -azs, axaz1_c,
			azs, ayay1_cpc, -axs,
			axaz1_c, axs, azaz1_cpc
			);
		return rotVert = mul(rotMatrix, verts);
	}
	ENDHLSL

	Pass{
		Name "ForwardLit"
		Tags{
		"LightMode" = "LightweightForward"}
		ZWrite Off
		//ZWrite On
		Blend SrcAlpha OneMinusSrcAlpha
		
		HLSLPROGRAM
		#pragma target 3.0
		#pragma vertex vert
		#pragma fragment frag

		#define SAMPLE_SH_X2MSCENE
		#define X2M_ENVGI
		#define X2M_GI_BAKED

		//#pragma multi_compile_fwdbase
		//#pragma multi_compile DIRECTIONAL 
		//#pragma multi_compile LIGHTPROBE_SH
		//#pragma multi_compile_instancing
		#pragma multi_compile INSTANCING_ON
		////use terrain sector shadowmask
		//#define _X2M_WORLDPOS_SHADOW 1

		struct v2f
		{
			float4 pos : SV_POSITION;
			float2 uv0 : TEXCOORD0;
			half3 normalDir : NORMAL;
			half3 cutGrass: TEXCOORD1;
			//UNITY_SHADOW_COORDS(2)
				//X2M_FOG_COORDS(3)
			float3 posWorld : TEXCOORD2;
			half3 ambient : TEXCOORD3;
			half3 lambert : TEXCOORD4;
			half3 specular : TEXCOORD5;
			//X2M_SHADOW_SSM_COORDS(8)
			//X2M_SHADOWMASK_COORDS(7)
			UNITY_VERTEX_INPUT_INSTANCE_ID
		};
		struct appdata_full
		{
			float4 vertex : POSITION;
			float4 tangent : TANGENT;
			float3 normal : NORMAL;
			float4 texcoord : TEXCOORD0;
			float4 texcoord1 : TEXCOORD1;
			float4 texcoord2 : TEXCOORD2;
			float4 texcoord3 : TEXCOORD3;
			half4 color : COLOR;
			UNITY_VERTEX_INPUT_INSTANCE_ID
		};

UNITY_INSTANCING_BUFFER_START(Props)
		UNITY_DEFINE_INSTANCED_PROP(half4, _lightmapUV)
		UNITY_DEFINE_INSTANCED_PROP(half4, _ColorMask)
UNITY_INSTANCING_BUFFER_END(Props)

		v2f vert(appdata_full v)
		{
			v2f o = (v2f)0;
			UNITY_SETUP_INSTANCE_ID(v);
            o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
			//o.normalDir = normalize(mul(v.normal, UNITY_MATRIX_I_M));
			v.vertex.xyz += v.vertex.xyz*_BladeHeight.zwz;
			float3 verts = v.vertex.xyz;
			half3x3 RSMat = half3x3(UNITY_MATRIX_M[0][0], UNITY_MATRIX_M[0][1], UNITY_MATRIX_M[0][2],
				UNITY_MATRIX_M[1][0], UNITY_MATRIX_M[1][1], UNITY_MATRIX_M[1][2],
				UNITY_MATRIX_M[2][0], UNITY_MATRIX_M[2][1], UNITY_MATRIX_M[2][2]
				);
			verts = mul(RSMat, v.vertex.xyz);

			//begin grass animation
			_AnimateTimeRand = _AnimateTimeEnd - _AnimateTime;
			_VelocityRand = _VelocityInitEnd - _VelocityInit;
			_AriseGRand = _AriseGravityEnd - _AriseGravity;
			_AriseVRand = _AriseVelocityInitEnd - _AriseVelocityInit;
			_RotRand = _RotVelocityInitEnd - _RotVelocityInit;
			_RotVelocityInit = (_RotVelocityInitEnd + _RotVelocityInit) / 2;

			float3 rootPos = float3(UNITY_MATRIX_M[0][3], UNITY_MATRIX_M[1][3], UNITY_MATRIX_M[2][3]);
			float3 root = rootPos - _WorldOffset.xyz;
			float4 posWorld = float4(root + verts, 1);

			half4 SkillforGrassDirectionEncode = GetSkillforGrassDirectionEncode(root);
			half4 SkillforGrassTimeEncode = GetSkillforGrassTimeEncode(root);

			//throw away grass not being cut or has already been burned 
			if (SkillforGrassTimeEncode.x < 0.9 || SkillforGrassTimeEncode.y > SkillforGrassTimeEncode.x)
			{
				o.pos.w = 0;
				return o;
			}

			half t = (SkillforGrassTimeEncode.x - 1);
			o.cutGrass.x = t;
			//translation diretion
			half2 animGrassDir = half2(0, 0);
			half2 skillDir = half2(0, 0);
			half2 initDir = half2(0,0);

			//decode skill direction
			half temp = SkillforGrassDirectionEncode.a / 100;
			half tempx = 100 * frac(temp);
			skillDir.x = (tempx - 10) / 10;
			half tempz = temp - frac(temp);
			skillDir.y = (tempz - 10) / 10;

			//decode character position when cast skill 
			float2 castSkillPos = float2(_TerrainBasePos.x + SkillforGrassTimeEncode.b, _TerrainBasePos.z + SkillforGrassTimeEncode.a);
			half2 centerDir = normalize(root.xz - castSkillPos);
			//initDir的y分量对应世界坐标的z分量
			initDir.x = (1 - _SkillDirection) * centerDir.x + _SkillDirection * skillDir.x;
			initDir.y = (1 - _SkillDirection) * centerDir.y + _SkillDirection * skillDir.y;

			half3 rotAxis = half3(initDir.y, 0, -initDir.x);

			//for direction vary, 
			//half randomValue = fmod(8191 * (rootPos.x + rootPos.z + rootPos.y), 127) / 127;
			half randomValue = frac(rootPos.x);
			half r1 = fmod(997.0*(randomValue), 211);
			r1 = r1 / 211 - 0.5;

			o.cutGrass.y = randomValue;
			half r2 = fmod(524287.0*(randomValue), 127);
			r2 = r2 / 127 - 0.5;

			half2 grassDir;
			grassDir.x = initDir.x +_DirRand * r1;
			grassDir.y = initDir.y +_DirRand * r2;
			grassDir = normalize(grassDir);

			animGrassDir.x = grassDir.x + t * _WindDirX;
			animGrassDir.y = grassDir.y + t * _WindDirZ;

			////for height vary, increase height noise
			half hnoise;
			hnoise = fmod(8191.0 * (rootPos.x + rootPos.z), 131);
			hnoise = hnoise / 131;

			half hVelocityInitNoise;
			hVelocityInitNoise = fmod(8191.0*(hnoise), 11);
			hVelocityInitNoise = _AriseVRand * hVelocityInitNoise / 11;

			half y = (_AriseVelocityInit + hVelocityInitNoise)*t + 0.4f*abs(sin(8 * t)) - (_AriseGravity)*t;

			////for velocity vary
			half animateVelocity = 0;
			half animDeltaDisp = 0;
			animateVelocity = (_VelocityInit + _VelocityRand * randomValue) * (1 - 1 / (_VelocityDamp * t + 1)) / t + _VelocityFinal;
			animDeltaDisp = (animateVelocity)* t;

			if (t >= _AnimateTime + _AnimateTimeRand * randomValue)
			{
				o.pos.w = 0;
				return o;
			}

			if (SkillforGrassTimeEncode.x > 0)
			{
				//scale
				half scale = saturate(1 - _ScaleDamp*t);
				verts *= scale;

				//rotate
				verts = RotateAboutAxis(t * 5, rotAxis, verts);
				//debug: o.specular = t;
				//translate
				//X;
				root.x += animDeltaDisp*animGrassDir.x +t;
				//Z
				root.z += animDeltaDisp*animGrassDir.y +t;
				//Y
				root.y += y;// +(_AnimateNoiseAmp * r3)*sin(_AnimateNoiseFreq*t*randomValue);// +animateNoiseAmp*sin(2 * animateNoiseFreq*o.pos.x*randomValue);
				posWorld = float4(root + verts, 1);
				//增加一些花穗的随风摆动
				//posWorld.xyz = CalRunWindPos(posWorld.xyz, v.vertex.y, 1.2);
			}
		
			o.posWorld = posWorld.xyz;
			o.pos = mul(UNITY_MATRIX_VP, posWorld);
			//UNITY_TRANSFER_SHADOW(o, v.texcoord1.xy);

			//half3 lightDir = normalize(_MainLightPosition.xyz);
			//half3 viewDir = normalize(UnityWorldSpaceViewDir(posWorld.xyz));
			// nl = abs(dot(lightDir, o.normalDir))*0.5 + 0.5;
			//half3 h = normalize(lightDir + viewDir);
			//half nh = max(0, dot(o.normalDir, h));
			//half spec = pow(nh, _SpecularPower*128.0) * _Gloss;
			//spec = clamp(spec, 0.0, 100.0);
			//o.specular = _MainLightColor.rgb * spec;
			//o.lambert = saturate(_MainLightColor.rgb * nl);
			//o.lambert = _MainLightColor.rgb * nl;
			//o.ambient = max(half3(0, 0, 0), SampleSH(o.normalDir));

			return o;
		}

        void ColorLerp(half3 Color, half3 CMask, half3 CMaskG, half3 Flip_CMask, half4 VColorMask, out half3 col)
        {
            half3 ColorTop = lerp(Color, CMaskG, VColorMask.y);
            half3 CMaskTop = lerp(CMask, Flip_CMask, VColorMask.z * VColorMask.x);
            ColorTop = lerp(ColorTop, CMaskTop, VColorMask.x);
            col = ColorTop;
        }

		half4 frag(v2f i) : COLOR
        {
			//return half4(i.specular,1); //debug rotate
			half t = i.cutGrass.x;
			half alpha = 1;
			_AnimateTimeRand = _AnimateTimeEnd - _AnimateTime;
			half termiTime = _AnimateTime + _AnimateTimeRand * i.cutGrass.y;
			half transitTransparentTime = _TransparentTime * termiTime;

			half tp = (t - transitTransparentTime) / (termiTime - transitTransparentTime);
			if (t > transitTransparentTime) {
				alpha = lerp(1, 0, tp);
			}
     //粗略模拟一下草的颜色
			float2 uv = i.uv0.xy;
			half4 c = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv) * _Color;
			clip(c.a - _Cutoff);
			half4 VColorMask = UNITY_ACCESS_INSTANCED_PROP(Props, _ColorMask);
            half3 ColorTop, ColorBottom;
            ColorLerp(_ColorTop, _CMaskTop, _CMaskTopG, _Flip_CMaskTopG, VColorMask, ColorTop);
            ColorLerp(_ColorBottom, _CMaskBottom, _CMaskBottomG, _Flip_CMaskBottomG, VColorMask, ColorBottom);
            ColorTop = lerp(ColorTop, ColorBottom, pow(1 - uv.y, _GradientS));
            ColorTop += _ColorHL * (1 - c.g) * VColorMask.a;
            c.rgb = ColorTop;
            //Light light = MainLight(i.posWorld);
            //half3 LightColor = light.color * light.distanceAttenuation;
            //c.rgb *= LightColor;
			return half4(c.rgb, alpha);
		}


	ENDHLSL
	}
		
	}
		//FallBack "Diffuse"
}
