Shader "URP/Environment/Grass/GrassBurnEncode"
{
	Properties
	{
		//for satisfy srp shader property requirement
		[HideInInSpector]_SkillforGrassTimeEncodeTex_TexelSize("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_InteractiveTex_TexelSize("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_MaskTex_TexelSize("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_CenterPos("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_Dif("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_SkillDir("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_CastSkillCharPos("", Vector) = (0, 0, 0, 0)
		[HideInInSpector]_SampleChannel("", int) = 0
	}

	SubShader
	{
		Tags{ "Queue" = "Geometry" "RenderPipeline" = "LightweightPipeline" "IgnoreProjector" = "True" "RenderType" = "Opaque" "PreviewType" = "Plane" }
		LOD 100

		HLSLINCLUDE
		#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/SurfaceInput.hlsl" 		
		#include "FoliageLighting.hlsl"
		#include "../../Common/Function/Scene_Common.hlsl"

		TEXTURE2D(_SkillforGrassTimeEncodeTex);		SAMPLER(sampler_SkillforGrassTimeEncodeTex);
		TEXTURE2D(_InteractiveTex);					SAMPLER(sampler_InteractiveTex);
		TEXTURE2D(_MaskTex);						SAMPLER(sampler_MaskTex);

		CBUFFER_START(UnityPerMaterial)
			half4 _SkillforGrassTimeEncodeTex_TexelSize;
			half4 _InteractiveTex_TexelSize;
			half4 _MaskTex_TexelSize;
			half4 _CenterPos;
			half4 _Dif;
			half3 _SkillDir;
			half3 _CastSkillCharPos;
			int _SampleChannel;
		CBUFFER_END

		ENDHLSL


		Pass
		{
			Tags{ "LightMode" = "LightweightForward" }
			Name "GrassTimeIncreaseandTexMove"
			ZWrite Off
			Cull off
			Lighting Off
			ZTest Always
		
			HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0

			struct appdata
			{
				half4 vertex : POSITION;
				half2 uv : TEXCOORD0;
			};

			struct v2f
			{
				half2 uv : TEXCOORD0;
				half2 uv1 : TEXCOORD1;
				half4 pos : SV_POSITION;
			};

			v2f vert(appdata v)
			{
				v2f o = (v2f)0;
				o.pos = half4(v.vertex.xyz, 1.0);

				half2 uv = v.uv;
				o.uv1 = v.uv;
				//o.uv2 = v.uv;
		#if UNITY_UV_STARTS_AT_TOP
				// DX 
				uv.y = 1.0 - uv.y;
				o.uv1.y = 1.0 - o.uv1.y;
				//o.uv2.y = 1.0 - o.uv2.y;
				_Dif.z *= -1;
				// OpenGL, don't need 1.0 - y
		#endif
				o.uv = uv + _Dif.xz * _SkillforGrassTimeEncodeTex_TexelSize.xy;
				return o;
			}

			half4 frag(v2f i) : SV_Target
			{
				//return tex2D(_MaskTex, i.uv);
				UNITY_SETUP_INSTANCE_ID(i);
				half4 moved = half4(0, 0, 0, 1);

				half4 interactiveTex = SAMPLE_TEXTURE2D(_InteractiveTex, sampler_InteractiveTex, i.uv1);
				half4 timeEncode = SAMPLE_TEXTURE2D(_SkillforGrassTimeEncodeTex, sampler_SkillforGrassTimeEncodeTex, i.uv);
				if (i.uv.x >= 0 && i.uv.x < 1 && i.uv.y >= 0 && i.uv.y < 1)
				{
					moved = timeEncode;
				}

				//采样_InteractiveTex贴图，由于该贴图在释放技能后每帧都随人物移动；而_SkillforGrassTimeEncodeTex只在释放技能后的动画期间移动；
				//因此加如下判断：如果该像素点<0.001说明标记已经被清除；此时也应该将_SkillforGrassTimeEncodeTex上的编码信息清除。
				if (interactiveTex.r < 0.001) {
					moved.r = 0;//clear grass cutoff time tag
				}
				if (interactiveTex.g < 0.001) {
					moved.g = 0;//clear grass burn time tag
				}

				if ((timeEncode.r > 0.9 && timeEncode.r < 1.2) || (timeEncode.g > 0.9 && timeEncode.g < 1.2))
				{
					//encode charPos when cast skill, x -> B channel, z -> A channel (note _CastSkillCharPos has already substracted the current terrain base pos)
					moved.b = _CastSkillCharPos.x;
					moved.a = _CastSkillCharPos.z;
				}

				//encode time, note moved.r == 1 means a skill in this range is triggered
				if (moved.r > 0.99) {
					moved.r += unity_DeltaTime.x;
					//moved.r += 1;
				}
				if (moved.g > 0.99) {
					moved.g += unity_DeltaTime.x;
				}
				return moved;
			}
			ENDHLSL
		}

		Pass
		{
			Name "MarkSkillRange"
			Tags{ "LightMode" = "LightweightForward" }

			ZWrite Off
			Cull off
			Lighting Off
			ZTest Always
			BlendOp MAX

			HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
//#pragma multi_compile_instancing
#pragma multi_compile INSTANCING_ON
#pragma target 3.0

			struct v2f
			{
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID//necessary only if you want to access properties in fragment shader
			};

			UNITY_INSTANCING_BUFFER_START(Props)
			UNITY_DEFINE_INSTANCED_PROP(half4, _maskStartUVSize)
			UNITY_DEFINE_INSTANCED_PROP(half4, _interactiveCastSkillPos)
			UNITY_DEFINE_INSTANCED_PROP(half4, _interactiveType)
			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);
				UNITY_TRANSFER_INSTANCE_ID(v, o);//necessary only if you want to access properties in fragment shader
				half4 maskStartUVSize = UNITY_ACCESS_INSTANCED_PROP(Props, _maskStartUVSize);
				half4 interactivePos = UNITY_ACCESS_INSTANCED_PROP(Props, _interactiveCastSkillPos);

				o.pos = mul(UNITY_MATRIX_M, half4(v.vertex.xyz, 1.0));
				////keep skill range stay in place that being cast
				////_interactivePos is On_Weapon params character's worldpos when cast skill, _CenterPos.xz is character's current worldpos;
				//如果256*256的RT范围设置为51.2m*51.2m  <--> 2*2 in NDC，那么1m <--> 5pixel <--> 1/25.6 in NDC;
				//如果512*512的RT范围设置为51.2m*51.2m  <--> 2*2 in NDC，那么1m <--> 10pixel <--> 1/25.6 in NDC;所以从世界坐标单位m到NDC转换要除以25.6；
				half posOffsetX = (interactivePos.x - _CenterPos.x) / 25.6;
				half posOffsetZ = (interactivePos.z - _CenterPos.z) / 25.6;
				o.pos.x += posOffsetX;
				o.pos.y += posOffsetZ;

				o.uv = v.texcoord.xy;	// now the (0, 0) is left top

				o.uv *= maskStartUVSize.zw;
				o.uv += maskStartUVSize.xy;
				o.uv *= _MaskTex_TexelSize.xy;

		//Untiy采样普通纹理时统一（0，0）在左下角，采样RT时需要变换y轴；以下旧代码有误因此注释掉
		//#if UNITY_UV_STARTS_AT_TOP
		//		// DX 
		//		o.uv.y = 1.0 - o.uv.y;	// after this, the (0, 0) is left bottom
		//#else
		//		// OpenGL, don't need 1.0 - y
		//								
		//#endif

				return o;
			}

			half4 frag(v2f IN) :SV_Target
			{
				UNITY_SETUP_INSTANCE_ID(IN);//necessary only if you want to access properties in fragment shader
				half4 type = UNITY_ACCESS_INSTANCED_PROP(Props, _interactiveType);
				//return half4(type.r, type.r, type.r, type.r);
				half4 maskValue = half4(0, 0, 0, 1);
				half4 sampleValue = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, IN.uv);
				////mask the skill range and encode intial time
				half sValue = 0;
				if (_SampleChannel == 0)
					sValue = round(sampleValue.r);
				else if (_SampleChannel == 1)
					sValue = round(sampleValue.g);
				else if (_SampleChannel == 2)
					sValue = round(sampleValue.b);
				else if (_SampleChannel == 3)
					sValue = round(sampleValue.a);

				if (type.g > 0.9)//Type.E_Fire: = new Color(1, 1, 0, 0);
				{//释放火烧技能,则将技能释放标志存到g通道, temp==1标志该地点有火技能释放
					maskValue.g = sValue;
				}
				else	
				{//释放刀砍技能，则将技能释放标志存到r通道, temp==1标志该地点有砍技能释放
					maskValue.r = sValue;
				}

				//maskValue.r = round(sampleValue.r);
				//maskValue *= half4(1, 0, 0, 0);
				return maskValue;
			}
			ENDHLSL
		}

	}
}
