Shader "KriptoFX/BFX/BFX_Decal"
{
	Properties
	{
		[HDR] _TintColor("Tint Color", Color) = (1,1,1,1)
		_MainTex("NormalAlpha", 2D) = "white" {}
		_LookupFade("Lookup Fade Texture", 2D) = "white" {}
		_Cutout("Cutout", Range(0, 1)) = 1
		_CutoutTex("CutoutDepth(XZ)", 2D) = "white" {}
	[Space]
		_SunPos("Sun Pos", Vector) = (1, 0.5, 1, 0)
			//[Toggle(CLAMP_SIDE_SURFACE)] _ClampSideSurface("Clamp side surface", Int) = 0
	}


		SubShader
		{
			Tags{ "Queue" = "AlphaTest"}
			Blend DstColor SrcColor
			//Blend SrcAlpha OneMinusSrcAlpha
			Cull Front
			ZTest Always
			ZWrite Off

			Pass
			{

				CGPROGRAM
					#pragma vertex vert
					#pragma fragment frag

					#pragma multi_compile_fog
					#pragma multi_compile_instancing
					#pragma multi_compile _ USE_CUSTOM_DECAL_LAYERS
					#pragma shader_feature CLAMP_SIDE_SURFACE
					#pragma multi_compile _ USE_CUSTOM_DECAL_LAYERS_IGNORE_MODE

					#include "UnityCG.cginc"

					sampler2D _MainTex;
					sampler2D _Flowmap;
					sampler2D _LookupFade;
					sampler2D _CutoutTex;

					float4 _MainTex_ST;
					float4 _MainTex_NextFrame;
					float4 _CutoutTex_ST;

					UNITY_INSTANCING_BUFFER_START(Props)
						UNITY_DEFINE_INSTANCED_PROP(half4, _TintColor)
						UNITY_DEFINE_INSTANCED_PROP(half, _Cutout)
						UNITY_DEFINE_INSTANCED_PROP(float, _LightIntencity)
					UNITY_INSTANCING_BUFFER_END(Props)


					half4 _CutoutColor;
					half4 _FresnelColor;
					half4 _DistortionSpeedScale;

					UNITY_DECLARE_TEX2DARRAY(_CameraDepthTexture);
					sampler2D _LayerDecalDepthTexture;
					float4 _DepthPyramidScale;

					half InterpolationValue;
					half _AlphaPow;
					half _DistortSpeed;
					half _DistortScale;
					float4 _SunPos;
					half _DepthMul;
					half3 _DecalForwardDir;

					struct appdata_t {
						float4 vertex : POSITION;
						float4 normal : NORMAL;
						half4 color : COLOR;
						UNITY_VERTEX_INPUT_INSTANCE_ID
					};

					struct v2f {
						float4 vertex : SV_POSITION;
						half4 color : COLOR;

						float4 screenUV : TEXCOORD0;
						float4 ray : TEXCOORD1;
						float3 rayCameraOffset : TEXCOORD2;
						float3 viewDir : TEXCOORD3;
						float4 screenPos : TEXCOORD4;

						//UNITY_FOG_COORDS(4)

						UNITY_VERTEX_INPUT_INSTANCE_ID
						UNITY_VERTEX_OUTPUT_STEREO
					};


					v2f vert(appdata_t v)
					{
						v2f o;
						UNITY_SETUP_INSTANCE_ID(v);
						UNITY_TRANSFER_INSTANCE_ID(v, o);
						UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

						o.vertex = UnityObjectToClipPos(v.vertex);
						o.color = v.color;


						o.screenUV = ComputeScreenPos(o.vertex);
						//o.screenUV.xy *= _DepthPyramidScale.xy;

						o.viewDir = normalize(ObjSpaceViewDir(v.vertex));
						o.screenPos = ComputeGrabScreenPos(o.vertex);

						float3 viewRay = UnityObjectToViewPos(v.vertex).xyz;
						o.ray.w = viewRay.z;
						viewRay *= -1;
						o.ray.xyz = mul((float3x3)mul(unity_WorldToObject, UNITY_MATRIX_I_V), viewRay);
						o.rayCameraOffset = mul(mul(unity_WorldToObject, UNITY_MATRIX_I_V), float4(0, 0, 0, 1)).xyz;

						return o;
					}


					half4 frag(v2f i) : SV_Target
					{
						UNITY_SETUP_INSTANCE_ID(i);


	#if USE_CUSTOM_DECAL_LAYERS

						float depth = tex2D(_LayerDecalDepthTexture, i.screenUV.xy / i.screenUV.w);

						i.screenUV.xy *= _DepthPyramidScale.xy;
						float depthMask = UNITY_SAMPLE_TEX2DARRAY_LOD(_CameraDepthTexture, float4(i.screenUV.xy / i.screenUV.w, 0, 0), 0);
						float fade = depth < depthMask - 0.0005 ? 0 : 1;

		#if USE_CUSTOM_DECAL_LAYERS_IGNORE_MODE
							fade = 1 - fade;
							depth = depthMask;
		#endif
	#else
						i.screenUV.xy *= _DepthPyramidScale.xy;
						float depth = UNITY_SAMPLE_TEX2DARRAY_LOD(_CameraDepthTexture, float4(i.screenUV.xy / i.screenUV.w, 0, 0), 0);
	#endif

						i.ray /= i.ray.w;
						float zEye = LinearEyeDepth(depth);
						float3 decalSpaceScenePos = i.rayCameraOffset + i.ray.xyz * zEye;



						float3 stepVal = saturate((0.5 - abs(decalSpaceScenePos.xyz)) * 10000);
						half lookupHeight = tex2D(_LookupFade, float2(decalSpaceScenePos.y + 0.5, 0));

						float projClipFade = stepVal.x * stepVal.y * stepVal.z * lookupHeight;
	#if USE_CUSTOM_DECAL_LAYERS
						projClipFade *= fade;
	#endif


	#if CLAMP_SIDE_SURFACE
	#ifdef UNITY_UV_STARTS_AT_TOP
						half3 n = normalize(cross(ddx(decalSpaceScenePos), ddy(decalSpaceScenePos) * _ProjectionParams.x));
	#else
						half3 n = normalize(cross(ddx(decalSpaceScenePos), -ddy(decalSpaceScenePos) * _ProjectionParams.x));
	#endif

						half angle = abs(dot(n, _DecalForwardDir));

						angle = angle > 0.1 ? 1 : 0;
						projClipFade *= angle;
						//return float4(saturate(angle), 0, 0, 1);

	#endif


						float2 uv = decalSpaceScenePos.xz + 0.5;
						float2 uvMain = uv * _MainTex_ST.xy + _MainTex_ST.zw;
						float2 uvCutout = (decalSpaceScenePos.xz + 0.5) * _CutoutTex_ST.xy + _CutoutTex_ST.zw;

						half4 normAlpha = tex2D(_MainTex, uvMain);
						half4 res = 0;
						res.a = saturate(normAlpha.w * 2);
						if (res.a < 0.1 || projClipFade < 0.1) discard;

						normAlpha.xy = normAlpha.xy * 2 - 1;
						float3 normal = normalize(float3(normAlpha.x, 1, normAlpha.y));

						half3 mask = tex2D(_CutoutTex, uvCutout).xyz;
						half cutout = 0.5 + UNITY_ACCESS_INSTANCED_PROP(Props, _Cutout) * i.color.a * 0.5;

						half alphaMask = saturate((mask.r - (cutout * 2 - 1)) * 20) * res.a;
						half colorMask = saturate((mask.r - (cutout * 2 - 1)) * 5) * res.a;
						res.a = alphaMask;
						res.a = saturate(res.a * projClipFade);


						float intencity = UNITY_ACCESS_INSTANCED_PROP(Props, _LightIntencity);
						float light = max(0.001, dot(normal, normalize(_SunPos.xyz)));
						light = pow(light, 150) * 3 * intencity;
						light *= (1 - mask.z * colorMask);

						float4 tintColor = UNITY_ACCESS_INSTANCED_PROP(Props, _TintColor);
						#if !UNITY_COLORSPACE_GAMMA
								tintColor = tintColor * 1.35;
						#endif
						res.rgb = lerp(tintColor.rgb, tintColor.rgb * 0.25, mask.z * colorMask) + light;


						half fresnel = (1 - dot(normal, normalize(i.viewDir)));
						fresnel = pow(fresnel + 0.1, 5);

						//UNITY_APPLY_FOG_COLOR(i.fogCoord, res, half4(1, 1, 1, 1));
						return lerp(0.5, res, res.a);

						return res;
					}

				ENDCG
		}

		}

}
