// 统一处理UnityGI的算法
#ifndef UNITY_GI_BASE_INCLUDE 
	#define UNITY_GI_BASE_INCLUDE
	#include "UnityCG.cginc"
	#include "Lighting.cginc"
	#include "AutoLight.cginc"
	#include "SimLightSpecular.cginc"

	// Forward Base 通用的参数结构
	struct v2f_Base {
		float4 pos : SV_POSITION;
		float2 uv : TEXCOORD0;
		float4 tSpace0 : TEXCOORD1;
		float4 tSpace1 : TEXCOORD2;
		float4 tSpace2 : TEXCOORD3;
		UNITY_FOG_COORDS(4)
		SHADOW_COORDS(5)
		#ifndef LIGHTMAP_OFF
			float4 lmap : TEXCOORD6;
		#endif
        #if UNITY_SHOULD_SAMPLE_SH
            half3 sh : TEXCOORD7; // SH
        #endif
	};

	// Forward Add 使用的参数结构
	struct v2f_Add {
		float4 pos : SV_POSITION;
		float4 uv : TEXCOORD0;
		float3 lightDir : TEXCOORD1;
		float3 worldPos : TEXCOORD2;
		UNITY_FOG_COORDS(3)
		SHADOW_COORDS(4)
	};

	GLOBAL_LIGHT_INFORMATION

#if PLAYER_HALO_ON
    uniform float _PlayerLightStrength;
	uniform float4 _PlayerLightPos;
	
	fixed LightColorFromWorld(float3 pos)
	{
		float lengthSqr = 0;
		float toLightX = pos.x - _PlayerLightPos.x;
		float toLightY = pos.y - _PlayerLightPos.y;
		float toLightZ = pos.z - _PlayerLightPos.z;
		lengthSqr += toLightX * toLightX;
		lengthSqr += toLightY * toLightY;
		lengthSqr += toLightZ * toLightZ;
		return _PlayerLightStrength * 2.0 / (1.0 + lengthSqr);
	}
#endif

	// 通用ForwardBase的Vertex代码
	v2f_Base vert_Base(appdata_full v)
	{
		v2f_Base o;
		UNITY_INITIALIZE_OUTPUT(v2f_Base, o);
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = v.texcoord;
		float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
		fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
		fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
		fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
		o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
		o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
		o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
		TRANSFER_SHADOW(o)
		UNITY_TRANSFER_FOG(o,o.pos);
		#ifndef LIGHTMAP_OFF
			o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
			#ifndef DYNAMICLIGHTMAP_OFF
				o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
			#endif
		#endif
		#if UNITY_SHOULD_SAMPLE_SH
			o.sh = 0;
			// Approximated illumination from non-important point lights
			#ifdef VERTEXLIGHT_ON
				o.sh += Shade4PointLights (
				unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
				unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
				unity_4LightAtten0, worldPos, worldNormal);
			#endif
			o.sh = ShadeSHPerVertex (worldNormal, o.sh);
		#endif
		return o;
	}

	// 通用ForwardAdd的Vertex代码
	v2f_Add vert_Add (appdata_full v) {
		v2f_Add o;
		UNITY_INITIALIZE_OUTPUT(v2f_Add, o);
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = v.texcoord;
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		// 使用真实光源参数,光照贴图将不会走ForwardAdd
		#ifdef USING_DIRECTIONAL_LIGHT
			fixed3 lightDir = _WorldSpaceLightPos0.xyz;
		#else
			fixed3 lightDir = normalize(UnityWorldSpaceLightDir(o.worldPos));
		#endif
		TANGENT_SPACE_ROTATION;
		o.lightDir = normalize(MUL_3x3_WITH_VECTOR(rotation, MUL_3x3_WITH_VECTOR(unity_WorldToObject, lightDir)));
		TRANSFER_SHADOW(o)
		UNITY_TRANSFER_FOG(o, o.pos);
		return o;
	}

	float3 GetWorldPos(v2f_Base i)
	{
		return float3(i.tSpace0.w, i.tSpace1.w, i.tSpace2.w);
	}
	
	float3 GetLightDir(float3 worldPos)
	{
		#ifndef LIGHTMAP_OFF
			fixed3 lightDir = _DirectionalLight.xyz;
		#else
			#ifndef USING_DIRECTIONAL_LIGHT
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
			#else
				fixed3 lightDir = _WorldSpaceLightPos0.xyz;
			#endif
		#endif
		return lightDir;
	}

	// 不使用SurfaceOutput的LambertLight,直接使用ndotl执行计算
	inline fixed3 LambertLight (half3 albedo, half ndotl, UnityLight light)
	{
		fixed3 c = albedo * light.color * ndotl;
		return c;
	}

	fixed3 GetUnityGiColorFull(half3 color, v2f_Base i, half3 worldNormal, half3 worldPos, half3 lightDir, float ndotl, float atten)
	{
		// 构造常规函数UnityGI
		UnityGI gi;
		UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
		gi.indirect.diffuse = 0;
		gi.indirect.specular = 0;
		#if !defined(LIGHTMAP_ON)
			gi.light.color = _LightColor0.rgb;
			gi.light.dir = lightDir;
			gi.light.ndotl = ndotl;
		#endif
		// 构造常规函数UnityGIInput
		UnityGIInput giInput;
		UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
		giInput.light = gi.light;
		giInput.worldPos = worldPos;
		giInput.atten = atten;
		#ifndef LIGHTMAP_OFF
			giInput.lightmapUV = i.lmap;
		#else
			giInput.lightmapUV = 0.0;
		#endif
		#if UNITY_SHOULD_SAMPLE_SH
			giInput.ambient = i.sh;
		#else
			giInput.ambient.rgb = 0.0;
		#endif
		giInput.probeHDR[0] = unity_SpecCube0_HDR;
		giInput.probeHDR[1] = unity_SpecCube1_HDR;
		#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
			giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
		#endif
		#if UNITY_SPECCUBE_BOX_PROJECTION
			giInput.boxMax[0] = unity_SpecCube0_BoxMax;
			giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
			giInput.boxMax[1] = unity_SpecCube1_BoxMax;
			giInput.boxMin[1] = unity_SpecCube1_BoxMin;
			giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
		#endif
		// 计算最终UnityGI
		gi = UnityGlobalIllumination(giInput, 1.0, worldNormal);
		// 相当于LightingBlinnPhong(o, worldViewDir, gi);
		fixed3 albedo = color;
		color = LambertLight(albedo, ndotl, gi.light);
		// 不会使用分离贴图处理
		#if defined(DIRLIGHTMAP_SEPARATE)
			#ifdef LIGHTMAP_ON
				color += LambertLight (albedo, ndotl, gi.light2);
			#endif
			#ifdef DYNAMICLIGHTMAP_ON
				color += LambertLight (albedo, ndotl, gi.light3);
			#endif
		#endif
		#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
			color += albedo * gi.indirect.diffuse;
		#endif
		return color;
	}
	
	#define GET_UNITY_GI_COLOR \
		half3 worldPos = GetWorldPos(i); \
		half3 lightDir = GetLightDir(worldPos); \
		fixed ndotl = LambertTerm(worldNormal, lightDir); \
		half atten = SHADOW_ATTENUATION(i); \
		fixed3 giColor = GetUnityGiColorFull(c.rgb, i, worldNormal, worldPos, lightDir, ndotl, atten)
#endif