#ifndef SCENE_PBR
#define SCENE_PBR
		#include "../../Common/Function/URP_Common.hlsl"
		#include "Assets/URP/Shader/HLSL/Common/Template Shader/Define.hlsl"
		#include "Assets/URP/Shader/HLSL/Common/Template Shader/Hole.hlsl"
		#include "../../Environment/WeatherSystem/Weather.hlsl"
		#include "BlackHole.hlsl"
		#include "../../Environment/Sky&Fog/VolumetricFogForObject.hlsl"

		//CBUFFER_START(UnityPerMaterial)
		uniform half4 _Color,_Ambient;   
		uniform sampler2D _Metal_Mask;
		uniform half2 _BumpMap_ST;
		//uniform half _RampThreshold;
		//uniform half _RampSmooth;
		//uniform half4 _HColor;
		uniform half4 _SColor;
		uniform half4 _EnvShadow;
		uniform half _diffuse;
		//uniform half _LightIntensity;
		uniform half _NormalScale0;
		uniform half _NormalScale1;
		uniform half _UseHole;
	#ifdef _Terrain_Moblie
		TEXTURE2D(_Splat0); SAMPLER(sampler_Splat0);
		TEXTURE2D(_Control); SAMPLER(sampler_Control);
		TEXTURE2D(_Splat1); SAMPLER(sampler_Splat1);
		TEXTURE2D(_Splat2); SAMPLER(sampler_Splat2);
		TEXTURE2D(_Splat3); SAMPLER(sampler_Splat3);
		TEXTURE2D(_BumpSplat1); SAMPLER(sampler_BumpSplat1);
		TEXTURE2D(_BumpSplat2); SAMPLER(sampler_BumpSplat2);
		TEXTURE2D(_BumpSplat3); SAMPLER(sampler_BumpSplat3);
		sampler2D _ColorMask;
		uniform half4 _ColorMask_ST;
		uniform half3 _CMaskBottom;
		uniform half3 _CMaskBottomG;
		uniform half3 _Flip_CMaskBottomG;
		uniform half3 _ColorBottomFar;
		uniform half3 _CMaskBottomFar;
		uniform half3 _CMaskBottomGFar;
		uniform half3 _Flip_CMaskBottomGFar;
		uniform half _ColorStart,_ColorEnd;
		uniform half _HueShiftCM;
		uniform half _SatCM;
		uniform half _ValCM;
		uniform half _HueShiftFlipG;
		uniform half _SatFlipG;
		uniform half _ValFlipG;

		uniform half _ControlUV,_BlendUV;
		float4 _UvSize;
	#else
		TEXTURE2D(_DetailNormal); SAMPLER(sampler_DetailNormal);
		uniform float2 _DetailNormal_ST;
		uniform half _NormalScale2;
	#endif
		uniform half _UVSec; 
		uniform half _diffuse_intensity;
		uniform half _Roughness;
		uniform half _SpecStrength;
		uniform half _MetalStrength;
		uniform half4 _envir_brightness;
		uniform half _bloom_range;
		uniform half _BloomFactor;
		uniform half _SceneBloomFactor;
		uniform half _AlphaClip;
		uniform half _MainAlpha;
		uniform half _Metal_ON;
		//uniform half _Alpha_Metal;
		//uniform half _EMISSION;
	#ifdef USE_Blend
		sampler2D _BlendTex;
		TEXTURE2D(_BlendNormal); SAMPLER(sampler_BlendNormal);
		uniform half4 _BlendTex_ST;
		uniform half4 _BlendColor;
		uniform half3 _BlendDirection;
		uniform half _Blend;
		//uniform half _NormalScale2;
	#endif
			
	#ifdef INJECT_EFFECT_SNOW
		uniform half4 		_EffectExtension;
		uniform half 		_RampPower;
		uniform half		_Glitter;
		uniform half		_Aniso;
		uniform half		_Shininess;
		uniform half		_Specular;
		uniform half		_Emmission;
		TEXTURE2D(_SnowToon); SAMPLER(sampler_SnowToon);
		TEXTURE2D(_SnowNormal); SAMPLER(sampler_SnowNormal);
		TEXTURE2D(_SnowDetailNormal); SAMPLER(sampler_SnowDetailNormal);
		TEXTURE2D(_GlitterTex); SAMPLER(sampler_GlitterTex);
	#endif

	#ifdef INJECT_EFFECT_BURN
		TEXTURE2D(_BurnMask); SAMPLER(sampler_BurnMask);
		uniform half4 _EffectWeight;
	#endif
		//CBUFFER_END 
		
		#if defined(_Terrain_Moblie)
			//#define	Atten(NdotL) TNdotL(NdotL)
			#define	SpecLum(metal) _SpecStrength
			#define	RefStrength(metal) saturate(_envir_brightness.x)
			#define	SpecDistance(lineDistance) saturate((lineDistance-_ColorStart) / (_ColorEnd-_ColorStart))
		#else
			//#define	Atten(NdotL) NdotL
			#define	SpecLum(metal) lerp(_SpecStrength,_MetalStrength,metal)
			#define	RefStrength(metal) saturate(_envir_brightness.x*lerp(metal,1,_envir_brightness.y))
			#define	SpecDistance(lineDistance) 0
		#endif
		struct Attributes
		{
			float4 positionOS   : POSITION;
			half4 color:COLOR;
			float3 normalOS     : NORMAL;
			float4 tangentOS    : TANGENT;
			float2 uv     : TEXCOORD0;
			float2 lightmapUV   : TEXCOORD1;
			float2 uv3   : TEXCOORD2;
			UNITY_VERTEX_INPUT_INSTANCE_ID
		};
		struct v2f
		{
			float4 vertex : SV_POSITION;
			half4 color:COLOR;
			float2 uv : TEXCOORD0;
	#ifdef _Terrain_Moblie
			float2 ControlUv : TEXCOORD12;
			float2 BlendUv : TEXCOORD13;
	#endif
			float2 uv_Detail : TEXCOORD10;
			half3x3 tangentTransform:TEXCOORD1;//占用3个语义 2 3 4
			// half3 tangentWS : TEXCOORD2;
			// half3 bitangentWS : TEXCOORD3;
			float4 positionWS : TEXCOORD4;
			half3 normalWS : TEXCOORD5;
			half4 FogAndDistanceAndvPos : TEXCOORD6;
			float4 fogCoord : TEXCOORD11;
			float4 posW:TEXCOORD9;
			DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 8);
			UNITY_VERTEX_INPUT_INSTANCE_ID
		    UNITY_VERTEX_OUTPUT_STEREO
		};
		#include "Lightmap_Output.hlsl"
		#include "Scene_Common.hlsl"
		#include "PBR_Forward.hlsl"
#if defined(INJECT_EFFECT_SNOW) || defined(INJECT_EFFECT_BURN)	
		inline void inject_effect(v2f i,Light light, out float3 effect_color, out float its_weight)
		{
#ifdef INJECT_EFFECT_BURN
			its_weight = saturate(_EffectWeight.r+SAMPLE_TEXTURE2D(_BurnMask, sampler_BurnMask, i.uv*_EffectWeight.ba)*_EffectWeight.g);
			effect_color = 0;
			return;
#elif defined(INJECT_EFFECT_SNOW)			
			half2 PolyNormalUV = (i.positionWS.xz)/(_EffectExtension.xy);
			half Horizontal = smoothstep(0, 1, saturate((i.normalWS.y-0.5)/(0.9-0.5)));
			half2 HorizeontalDetailNormalUV = (i.positionWS.xz)/(_EffectExtension.zw);
			half2 DetailUV = Horizontal ? HorizeontalDetailNormalUV.xy : i.uv;

			half3 DetailNormal = normalize(UnpackNormal(SAMPLE_TEXTURE2D(_SnowDetailNormal,sampler_SnowDetailNormal,DetailUV)));

			half3 SnowNormal = normalize(UnpackNormal(SAMPLE_TEXTURE2D(_SnowNormal,sampler_SnowNormal, PolyNormalUV)));
			SnowNormal = normalize(SnowNormal);
			half3 CombineNormal = normalize(half3(SnowNormal.xy+DetailNormal.xy, SnowNormal.z));

			half3 NormalWS = mul(CombineNormal, i.tangentTransform);

			half3 Specular_val = SAMPLE_TEXTURE2D(_GlitterTex, sampler_GlitterTex, DetailUV);
			half3 viewDir = normalize(_WorldSpaceCameraPos-i.positionWS.xyz);
			half3 lightDir = light.direction;

			half3 H	= normalize(lightDir + viewDir);
			half NdotH = max(0, dot(NormalWS, H));
			half NdotL = dot(NormalWS, lightDir);
			half NdotV = dot(NormalWS, viewDir);

			half3 incoming_light = light.color;
			half brightness = dot(incoming_light, half3(0.29891, 0.58661, 0.11448));
			float3 shadowFactored = lerp(_EnvShadow.xyz, half3(1.0, 1.0, 1.0), light.shadowAttenuation);			
			incoming_light = brightness * _Emmission * shadowFactored;
			half3 shadow = incoming_light;
			half y = NdotL;
			half2 uv_Ramp = half2(_RampPower * NdotV, y);
			half3 ramp = SAMPLE_TEXTURE2D(_SnowToon,sampler_SnowToon,uv_Ramp);

			half3 specular 		= saturate(pow(NdotH, _Shininess * 128.0) * _Specular * Specular_val);
			half3 anisotropic	= max(0, sin(radians((NdotH + _Aniso) * 180)));
			anisotropic			= saturate(anisotropic * _Glitter);

			its_weight = Horizontal;
			effect_color = (ramp + anisotropic + specular) * shadow;
#endif			
		}
#endif					
		
		v2f vert (Attributes v)
		{
			v2f o;
			UNITY_SETUP_INSTANCE_ID(v);
			UNITY_TRANSFER_INSTANCE_ID(v, o);
			UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
			VertexPositionInputs vertexInput = GetVertexPositionInputs(v.positionOS.xyz);
			o.positionWS = float4(vertexInput.positionWS,v.positionOS.w);
			o.vertex = vertexInput.positionCS;
			
		#ifdef _Terrain_Moblie
			o.FogAndDistanceAndvPos.w= mul(UNITY_MATRIX_MV, v.positionOS).z;
			float2 PosW_Uv = float2(o.positionWS.xz/_UvSize.xy+(half2(0.5,0.5)-_UvSize.zw/_UvSize.xy));
			o.BlendUv = (_BlendUV == 0)?v.uv: ((_BlendUV == 1)?v.uv3:PosW_Uv);
			o.ControlUv = (_ControlUV == 0)?v.uv: ((_ControlUV == 1)?v.uv3:PosW_Uv);
		#endif
			o.uv_Detail = (_UVSec == 0)?v.uv:v.uv3;
			o.uv = v.uv;
			half fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
			VertexNormalInputs normalInput = GetVertexNormalInputs(v.normalOS, v.tangentOS);
			o.normalWS = normalInput.normalWS;
			// o.tangentWS = normalInput.tangentWS;
			// o.bitangentWS = normalInput.bitangentWS;
			o.tangentTransform = half3x3(normalInput.tangentWS, normalInput.bitangentWS, normalInput.normalWS);
			float lineDistance = distance(o.positionWS.xyz, _WorldSpaceCameraPos.xyz);
			o.posW = VertCalaShadow(o.positionWS, _DirX, _DirY);
			o.FogAndDistanceAndvPos.xy = float2(fogCoord,lineDistance);
			o.fogCoord = VolumetricFog_GetFogCoord(vertexInput.positionNDC, vertexInput.positionVS.z);
			OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUV);
			OUTPUT_SH(normalInput.normalWS.xyz, o.vertexSH);
			o.color = v.color;
			return o;
		}
		half4 frag_Pbr (v2f i, half4 c, half3 Normal, half alpha, out Light light) : SV_Target
		{
			UNITY_SETUP_INSTANCE_ID(i);
			UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
			#ifdef _Terrain_Moblie
			half smoothness = 0.5;	// TODO : 
			ApplyRainningByTerrain(Normal, smoothness, c, i.positionWS.xyz, 1);
			#endif
			light = MainLight(i.positionWS);

			half metal = _Metal_ON?c.a:0;
		#ifdef _Alpha_Metal
			metal = tex2D(_Metal_Mask,i.uv).r*_Metal_ON;
		#endif
			half3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.positionWS.xyz);
			half NdotL = saturate(dot(Normal, light.direction));
		//Env
			half3 bakeGI;
			LightmapResult(light,i,bakeGI,Normal,i.positionWS.xyz);	
		//Atten
			light.shadowAttenuation = FragCalaShadowAtten(light.shadowAttenuation, i.posW, _Time.x, _Speed, _ShadowAlphaRatio, _ShadowTex);
			half Atten = lerp(NdotL* light.shadowAttenuation,1,saturate(_envir_brightness.z));
		//PBR
			BRDFData brdfData;
			CustInitializeBRDFData(c.rgb, _Metallic*metal, half3(0.0h, 0.0h, 0.0h), _Roughness*alpha, 1, brdfData);
			half SpecDis = 1-SpecDistance(i.FogAndDistanceAndvPos.y);
			c.rgb = CustGlobalIllumination(brdfData, bakeGI , 1, Normal, viewDir,RefStrength(metal)*SpecDis*alpha);
			half4 PBRResult = CustLightingPhysicallyBased(brdfData, light, light.color, Atten, Normal, viewDir, SpecLum(metal)*alpha);
			c.rgb += PBRResult.rgb;
		//point
		#ifdef _ADDITIONAL_LIGHTS
			uint pixelLightCount = GetAdditionalLightsCount();
			for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
			{
				Light additional_light = GetAdditionalLight(lightIndex, i.positionWS);
				half3 attenuatedLightColor = additional_light.color * (additional_light.distanceAttenuation * additional_light.shadowAttenuation);
				c.rgb += LightingLambert(attenuatedLightColor, additional_light.direction, Normal);
			}
		#endif
		#ifdef _EMISSION
			c.rgb += SampleEmission(i.uv, _EmissionColor.rgb, TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap));
		#endif
			c.rgb *= _Color;
			c.rgb *= BalckHole_GetLightIntensity(i.positionWS);
			//c.rgb = bakeGI;
			//c.rgb = VolumetricFog_GetFog(c.rgb, i.fogCoord);
			c.a = 1;
			return c;
		}

		half4 frag_Common_Color(v2f i,half4 col)
		{
			half3 Normal;half4 nor2=half4(0.5,0.5,1,1);
			//half3x3 tangentTransform = half3x3(i.tangentWS, i.bitangentWS, i.normalWS);
			half4 nor1 = SampleNormalAlpha(i.uv*_BumpMap_ST.xx, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap),_NormalScale1);
			#if !defined(_Terrain_Moblie)
			nor2 = SampleNormalAlpha(i.uv_Detail*_DetailNormal_ST.xx, TEXTURE2D_ARGS(_DetailNormal, sampler_DetailNormal),_NormalScale0); 
			#endif
			Normal = normalize(half3(nor1.xy+nor2.xy,nor1.z));
		#ifdef COLOR_HSV
			col.rgb = replace_color_with_hsv (col.rgb, 1, _HueShift, _Sat, _Val, 1);
		#endif
		#ifdef USE_Blend
			half3 N = normalize(mul( Normal.rgb, i.tangentTransform ));
			half3 BlendTex = tex2D( _BlendTex, i.uv*_BlendTex_ST.xx )*_BlendColor.rgb;
			half BlendDir = dot(N, _BlendDirection.xyz)+_Blend;
			half4 BlendN = SampleNormalAlpha(i.uv*_BlendTex_ST.xx, TEXTURE2D_ARGS(_BlendNormal, sampler_BlendNormal),_NormalScale2);
			BlendN.a *= 1-_BlendColor.a;
			BlendN = lerp(half4(Normal,0),BlendN,smoothstep(0,1,BlendDir)*i.color.a);
			col.rgb = lerp(col.rgb,BlendTex,smoothstep(0,1,BlendDir)*i.color.a);
			//col.rgb = lerp(col.rgb,BlendTex,nor1.a);
			half alpha = BlendN.a;Normal = half3(BlendN.xy,Normal.z);
		#else
			half alpha = nor1.a;
		#endif
			Normal = normalize(mul(Normal, i.tangentTransform));
			Light main_light = (Light)0;
			half4 result = frag_Pbr(i, col, Normal , alpha, main_light);

		#if defined(INJECT_EFFECT_SNOW) || defined(INJECT_EFFECT_BURN)
			half3 effect_result = 0;half effect_weight = 0;
			inject_effect(i, main_light, effect_result, effect_weight);
			result.rgb = lerp(result.rgb, effect_result, effect_weight);
		#endif

			return result * BalckHole_GetLightIntensity(i.positionWS);
		}
		half4 frag_Blend_Common (v2f i,half4 col,half4 Normal,half ColorM)
		{
			//half alpha=0;
		#ifdef _Terrain_Moblie
			half2 VColorMask;
			VColorMask.x =tex2Dlod(_ColorMask,float4(i.positionWS.xz/_ColorMask_ST.x,0,0)).r;
			VColorMask.y =tex2Dlod(_ColorMask,float4(i.positionWS.xz/_ColorMask_ST.y,0,0)).g;
			//i.VColorMask.x *= 1-step(i.VColorMask.y,0);
			half ColorDis = saturate((i.FogAndDistanceAndvPos.y-_ColorStart) / (_ColorEnd-_ColorStart));
#ifdef USE_FAST_HSV_COMPUTED	
			half3 CMaskBottomG = replace_color_with_hsv_fast(col.rgb, 0, 27);	
			half3 CMaskBottom = replace_color_with_hsv_fast(col.rgb, 9, 30);	
			//half3 Flip_CMaskBottomG = replace_color_with_hsv_fast(CMaskBottom, 18, 33);
#else
			/// the orininal version
			half3 CMaskBottomG = replace_color_with_hsv (col.rgb, 1, _HueShift, _Sat, _Val, _CMaskBottomG);
			half3 CMaskBottom = replace_color_with_hsv (col.rgb, 1, _HueShiftCM, _SatCM, _ValCM, _CMaskBottom);
			//half3 Flip_CMaskBottomG = replace_color_with_hsv (CMaskBottom, 1, _HueShiftFlipG, _SatFlipG, _ValFlipG, _Flip_CMaskBottomG);
#endif
			CMaskBottomG = lerp(col.rgb,CMaskBottomG,VColorMask.y);
			//CMaskBottom = lerp(CMaskBottom,Flip_CMaskBottomG,i.VColorMask.z);
			half3 ColorBottom = lerp(CMaskBottomG,CMaskBottom,VColorMask.x);

			half3 ColorBottomFar = lerp(_ColorBottomFar,_CMaskBottomGFar,VColorMask.y);
			//half3 CMaskBottomFar = lerp(_CMaskBottomFar,_Flip_CMaskBottomGFar,i.VColorMask.z*i.VColorMask.x);
			ColorBottomFar = lerp(ColorBottomFar,_CMaskBottomFar,VColorMask.x);

			ColorBottom = lerp(ColorBottom,ColorBottomFar,ColorDis);
			col.rgb = lerp(col.rgb,saturate(ColorBottom),ColorM);
			//alpha = Normal.a;
		#endif
			//half3x3 tangentTransform = half3x3(i.tangentWS, i.bitangentWS, i.normalWS);
			Normal.rgb = normalize(mul(Normal.rgb, i.tangentTransform));
			Normal.rgb = lerp(Normal.rgb,half3(0,1,0),ColorM);
			Light main_light = (Light)0;
			return frag_Pbr(i, col, Normal.rgb , Normal.a, main_light);
		}
#endif