shader "URP/Environment/Grass/GrassCalForce"{
	Properties{
		
		_CollisionTex("Collision (RGB)", 2D) = "white" {}
		_Height("Height", Float) = 1.15
		_UpOffset("_UpOffset", Range(-1, 1)) = 0.093
		[HideInSpector] _UpDir("Growth Direction", Vector) = (0, 1, 0, 0)
		//_GroundCoef("Ground Coefficient", Range(-1, 1)) = 0.0
		_CollisionCoef("Collision Coefficient", Range(0, 2)) = 0.8
		_CollisionTailSpeed("Collision Tail Speed", Range(0, 20)) = 6.5
		//_CollisionTailScale("Collision Tail Scale", Range(0, 20)) = 0.6
		//_TestDisplacement("Test Displacement", Vector) = (0, 0, 0, 0)
		
		//for satisfy srp shader property requirement
		[HideInSpector] _CollisionTex_TexelSize("Growth Direction", Vector) = (0, 1, 0, 0)
		[HideInSpector] _WorldOffset("Growth Direction", Vector) = (0, 1, 0, 0)
		[HideInSpector] _prevCenterPos("Growth Direction", Vector) = (0, 1, 0, 0)
		[HideInSpector] _CenterPos("Growth Direction", Vector) = (0, 1, 0, 0)
	}

	SubShader{
		Tags{"Queue" = "Overlay" "RenderPipeline" = "LightweightPipeline" "RenderType" = "Opaque" "IgnoreProjector" = "True"}
		Cull off
		
			HLSLINCLUDE
#include "/Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "/Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"

			TEXTURE2D(_CollisionTex);	SAMPLER(sampler_CollisionTex);
			
			static const int Run_Wind_Array_Length = 10;
			float4 _RunWindArray[Run_Wind_Array_Length];
			CBUFFER_START(UnityPerMaterial)
				float4 _CollisionTex_TexelSize;

				float4 _WorldOffset;
				float4 _prevCenterPos;
				float4 _CenterPos;
				half4 _UpDir;

				half _Height;
				half _UpOffset;
				
				//half _GroundCoef;
				half _CollisionCoef;
				half _CollisionTailSpeed;
				//half _CollisionTailScale;
			CBUFFER_END
			
			void DecodeRadiusForce(float a, inout float radius, inout float force)
			{
				float b = a / 1000.0;
				radius = frac(b);
				force = b - radius;
				radius *= 100.0;
				force /= 100.0;
			}

			float4 Collision(float3 p, float dt)
			{
				float4 ret = float4(0, 0, 0, 0);

				// collision force
				for (int i = 0; i < Run_Wind_Array_Length; i++)
				{
					if (_RunWindArray[i].w == 0)
						break;

					float2 vDif = p.xz - _RunWindArray[i].xz;
					float lengthDif = length(vDif);

					float radius = 0;
					float maxForce = 0;
					DecodeRadiusForce(_RunWindArray[i].w, radius, maxForce);

					if (lengthDif > radius)
						continue;
					float atten = lengthDif / radius;
					atten = 1.0 - atten;
					atten = max(0, atten);
					atten = pow(atten + 1.0 - _CollisionCoef, -2);
					//atten = max(0, atten);
					atten *= maxForce;

					//atten *= _CollisionCoef;
					//atten *= dt;
					//ret.xz += (atten * normalize(vDif));
					ret.xz += atten; 
				}

				return ret;
			}
		ENDHLSL

		Pass
		{
			Tags{ "LightMode" = "LightweightForward" }
			Name "GeometryGrassInteractiveMove"
			ZWrite Off
			ZTest Always
			//Blend One One

			HLSLPROGRAM
			#pragma target 3.0
			//#pragma enable_d3d11_debug_symbols
			#pragma vertex vert
			#pragma fragment frag
			//#pragma multi_compile_instancing
			#pragma multi_compile INSTANCING_ON
			//#include "GrassMatrix.hlsl"
			

			struct v2f
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
				float2 prevUV : TEXCOORD1;
				float3 worldPos : TEXCOORD2;
			};

			struct PSOutput
			{
				float4 collision : COLOR0;
			};

			//UNITY_INSTANCING_BUFFER_START(Props)
			//	UNITY_DEFINE_INSTANCED_PROP(float4, _PlayerPosAndForce)
			//	//UNITY_DEFINE_INSTANCED_PROP(float4, _WorldPosTest)
			//UNITY_INSTANCING_BUFFER_END(Props)
			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
			};
			v2f vert(appdata_full v)
			{
				
				v2f o;
				UNITY_SETUP_INSTANCE_ID(v);
				o.pos = float4(v.vertex.xyz, 1.0);	
				
				float2 posOffset = (v.texcoord.xy - float2(0.5, 0.5)) * 12.8;
				o.worldPos = _CenterPos.xyz;
				//o.worldPos.xz += posOffset;
				o.worldPos.x += posOffset.x;
				o.worldPos.z += posOffset.y;

				o.uv = v.texcoord.xy;
				o.prevUV = (o.worldPos.xz - _prevCenterPos.xz) / 12.8 + float2(0.5, 0.5);
				//o.prevUV = (_CenterPos.xz - _prevCenterPos.xz) / 12.8 + v.texcoord.xy;

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

			PSOutput frag(v2f IN)
			{
				float dt = unity_DeltaTime.z;// 1.0 / 60.0;	// TODO : set this time delta?

				float4 prevVCollision = float4(0, 0, 0, 1);
				if (IN.prevUV.x >= 0 && IN.prevUV.x < 1 && IN.prevUV.y >= 0 && IN.prevUV.y < 1)
				{
					prevVCollision = SAMPLE_TEXTURE2D(_CollisionTex, sampler_CollisionTex, IN.prevUV);
				}

				float4 vCollision = Collision(IN.worldPos, dt);
				if (dot(vCollision, vCollision) < 0.0001)
				{
					float len = length(prevVCollision.xz);
					if (len > 0.0001)
					{
						float nexLen = len * (1.0 - _CollisionTailSpeed * dt);
						nexLen = max(0, nexLen);
						vCollision.xz = (prevVCollision.xz / len) * nexLen;
					}
				}

				vCollision.yw = prevVCollision.yw;

				PSOutput psOut;
				psOut.collision = vCollision;
				return psOut;
			}
			ENDHLSL
		}
	}
}

