Shader "URP/Effects/ToonShader"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_Color("Color", Color) = (1,1,1,1)
		_ToonRamp("_Toon Ramp", 2D) = "white" {}
		_Emission("Emission", float) = 0.3
		_Cutoff("AlphaCutout", Range(0, 1)) = 0.39
	}
		SubShader
		{
			 Tags{"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True"}
			 LOD 300

			Pass
			{
				Tags{"LightMode" = "UniversalForward"}
				HLSLPROGRAM
				#pragma vertex vert
				#pragma fragment frag
			// make fog work
			/*
		  #pragma multi_compile _ LIGHTMAP_ON
		  #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
		  #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

		  #pragma multi_compile_fog

			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		  #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"

		  */

		    #pragma multi_compile_fog
			#pragma multi_compile_instancing
			#pragma multi_compile _ LIGHTMAP_ON
			#pragma multi_compile _ SHADOWS_SHADOWMASK
			//#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
			#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
			#pragma multi_compile _ADDITIONAL_LIGHTS

			#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" 
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
	
		 CBUFFER_START(UnityPerMaterial)
		   sampler2D _MainTex;
		   half4 _MainTex_ST;
		   half4 _Color;
		   sampler2D _ToonRamp;
		   half _Cutoff;
		   float _Emission;
		   CBUFFER_END

		struct appdata
		{
			float4 vertex : POSITION;
			float3 normal : NORMAL;
			float2 uv : TEXCOORD0;
		};

		struct v2f
		{
			float4 vertex : SV_POSITION;
			float3 worldNormal : NORMAL;
			float2 uv : TEXCOORD0;
#ifdef _MAIN_LIGHT_SHADOWS
			float4 shadowCoord : TEXCOORD1;
#endif
			float fogCoord : TEXCOORD2;
			};

			v2f vert(appdata v)
			{
				v2f o;
				//o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				//o.vertex = TransformWorldToHClip(o.worldPos);

				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.worldNormal = TransformObjectToWorldNormal(v.normal);

				//顶点变换：
				VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);

				//获取阴影UV
#if defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF)
				o.shadowCoord = GetShadowCoord(vertexInput);
#endif
				o.fogCoord = vertexInput.positionCS.z;
				o.vertex = vertexInput.positionCS;
				return o;
			}

			half4 frag(v2f i) : SV_Target
			{
				half4 col = tex2D(_MainTex, i.uv) * _Color;
				clip(col.a - _Cutoff);
				//获取主光源：
#ifdef _MAIN_LIGHT_SHADOWS
				Light light = GetMainLight(i.shadowCoord);
#else
				Light light = GetMainLight();
#endif

				half3 lightDir = light.direction;
#if defined(LIGHTMAP_ON)
				float3 worldLightDir = 0;
#else
				float3 worldLightDir = lightDir;
#endif
				//float4 fogCol = 1; //fog 方式1
				float density = 1;
				//SHADERGRAPH_FOG(i.worldPos, fogCol, density); //fog 方式1 慎用！！有坑
				density = ComputeFogFactor(i.fogCoord); //flog 方式2
				float n1 = saturate(dot(i.worldNormal, lightDir));
				//col = tex2D(_ToonRamp, float2(n1, n1)) * _MainLightColor.w;
				//return col * n1 + col * float4((1 - n1) * SHADERGRAPH_AMBIENT_EQUATOR.rgb, 1) ;

				//col.rgb = col.rgb * light.color + (1 - n1) * SHADERGRAPH_AMBIENT_EQUATOR.rgb  + col;
				//return col;
				col.rgb = col * tex2D(_ToonRamp, float2(n1, n1)).rgb;
#ifdef _MAIN_LIGHT_SHADOWS
				col.rgb = col.rgb * light.shadowAttenuation;
#endif
				//col.rgb = col.rgb * _MainLightColor.w;
				half diff = max(0, n1);
				col.rgb = col * diff * light.color  + col.rgb * SHADERGRAPH_AMBIENT_EQUATOR.rgb * 2 + col.rgb * _Emission;

				//col = lerp(fogCol, col, density); //fog 混合方式1
				col.rgb = MixFog(col.rgb, density); //fog 混合方式2
				return col;
			}
			ENDHLSL
		 }

		//UsePass "Universal Render Pipeline/Lit/DepthOnly"
	    //UsePass "Universal Render Pipeline/Lit/ShadowCaster"
		//UsePass "URP/DepthOnly/DepthOnlyCutoff"
		
		Pass
		{
				Name "ShadowCaster"
					Tags{"LightMode" = "ShadowCaster"}

					ZWrite On
					ZTest LEqual
					Cull back

					HLSLPROGRAM
				// Required to compile gles 2.0 with standard srp library
				#pragma prefer_hlslcc gles
				#pragma exclude_renderers d3d11_9x
				#pragma target 2.0

				#pragma multi_compile _ALPHATEST_ON
				// -------------------------------------
				// Material Keywords
				//#pragma shader_feature _ALPHATEST_ON

				//--------------------------------------
				// GPU Instancing
				#pragma multi_compile_instancing
				#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

				#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
				#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
				#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"

				#pragma vertex ShadowPassVertex
				#pragma fragment fragCutoff

				float3 _LightDirection;
				//sampler2D _MainTex;
				//SamplerState sampler_MainTex;
				
				TEXTURE2D(_MainTex);            
				SAMPLER(sampler_MainTex);
				half4 _MainTex_ST;
				half4 _Color;

				struct Attributes
				{
					float4 positionOS   : POSITION;
					float3 normalOS     : NORMAL;
					float2 texcoord     : TEXCOORD0;
					UNITY_VERTEX_INPUT_INSTANCE_ID
				};

				struct Varyings
				{
					float2 uv           : TEXCOORD0;
					float4 positionCS   : SV_POSITION;
				};

				float4 GetShadowPositionHClip(Attributes input)
				{
					float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
					float3 normalWS = TransformObjectToWorldNormal(input.normalOS);

					float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));

				#if UNITY_REVERSED_Z
					positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
				#else
					positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
				#endif

					return positionCS;
				}

				Varyings ShadowPassVertex(Attributes input)
				{
					Varyings output;
					UNITY_SETUP_INSTANCE_ID(input);

					output.uv = TRANSFORM_TEX(input.texcoord, _MainTex); 
					output.positionCS = GetShadowPositionHClip(input);
					return output;
				}

				half4 fragCutoff(Varyings i) : SV_TARGET
				{
					Alpha(SampleAlbedoAlpha(i.uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex)).a, _Color, _Cutoff);
					return 0;
				}
				ENDHLSL
			}
			
		}
}
