// Toon卡通渲染
uniform uint _DynHLight,_Specular_Mode;
uniform float _HighLightStrength;
uniform float _HLightLength;
uniform float _HLightFeather;
uniform float _MetalStrength;
uniform float _MainAlpha;
uniform float _envir_brightness;
struct CharDot
{
    float3 worldHalfDir;
    float ndhH;
    float ndhL;
    float VdotH;
    float ndhV;
};
void Chardot(Light light,float3x3 tangent,inout half3 worldNormal,float3 WPos,float2 uv, out CharDot chardot)
{
#ifdef _NORMALMAP
	half4 Normal = tex2D(_BumpMap,uv);
	half3 tangentNormal = UnpackNormal(Normal);
	worldNormal = normalize(mul( tangentNormal.rgb, tangent));
#else
	worldNormal = TransformObjectToWorldNormal(worldNormal);
#endif
	float3 lightDir = light.direction;
	float perDistanceAttenuation = light.distanceAttenuation;
	//#ifdef USE_MAIN_LIGHT_DIR
	#ifdef _ADDITIONAL_LIGHTS
		uint pixelLightCount = GetAdditionalLightsCount();
		for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
		{
			Light light = GetAdditionalLight(lightIndex, WPos);
			lightDir = lerp(light.direction, lightDir, step(light.distanceAttenuation, perDistanceAttenuation));
			perDistanceAttenuation = max(light.distanceAttenuation, perDistanceAttenuation);
		}
	#endif
	//#endif
	float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - WPos.xyz);
	float3 worldLightDir = normalize(lightDir*perDistanceAttenuation);
	chardot.worldHalfDir = normalize(worldViewDir+worldLightDir);
	chardot.ndhH = dot(worldNormal, chardot.worldHalfDir);
	chardot.ndhL = dot(worldNormal, worldLightDir);
	chardot.ndhV = saturate(dot(worldNormal, worldViewDir));
	chardot.VdotH = saturate(dot(worldViewDir, chardot.worldHalfDir));
}
void Rim(inout half3 col,float2 uv,float nv,half Width,out half rimStep)
{
	rimStep = smoothstep(-Width+1-_RimWidth, 1, nv);
	rimStep = rimStep * 0.5*(1-step(_RimWidth,0));
	half3 rim = rimStep * _RimColor;
#ifdef FLASH_SWITCH
	half2 flashuv = uv * _FlashFactor.zw + _FlashFactor.xy * _Time.y;
	half3 flash = tex2D(_FlashTex, flashuv);
	col += lerp(0,flash.r * _FlashStrength,rim);
#else
	col += rim;
#endif
}
uniform float _BackRimMax;
uniform float _BackRimMin,_Rim;
half3 StylizedFresnel(Light light , half nv, half3 normal, half rimMin, half rimMax)
{
	half rim = 1-nv;
	rim = smoothstep(rimMin, rimMax, rim);
	return rim * saturate(dot(normal, light.direction))*_BackRimColor*light.shadowAttenuation*_Rim;
}
half3 RampCol(sampler2D Ramp,half UvX,half UvY)
{
	half2 RampUV = half2(UvX, UvY);
	half3 Col = tex2D(Ramp, RampUV);
	return Col;
}
half StylizedSpecular(half specularTerm, half specSmoothness)
{
	return smoothstep(specSmoothness*0.5, 0.5 + specSmoothness*0.5, specularTerm);
}
half4 CustDirectBDRF(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS,half3 SpecMask,half atten)
{
    float3 halfDir = SafeNormalize(float3(lightDirectionWS) + float3(viewDirectionWS));

    float NoH = saturate(dot(normalWS, halfDir));
    half LoH = saturate(dot(lightDirectionWS, halfDir));
    float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;

    half LoH2 = LoH * LoH;
    half specularTerm = brdfData.roughness2 / ((d * d) * max(0.1h, LoH2) * brdfData.normalizationTerm);
#if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
    specularTerm = specularTerm - HALF_MIN;
    specularTerm = clamp(specularTerm, 0.0, 100.0);
#endif
	half r = brdfData.roughness2*0.85 + (1e-4h);
	specularTerm = lerp(specularTerm,StylizedSpecular(specularTerm,SpecMask.y*0.96+0.04)*(1/r),step(0.04,SpecMask.y));
	half3 brdf = specularTerm * brdfData.specular * (lerp(_MetalStrength,_SpecStrength,step(1,SpecMask.z))+5*SpecMask.x);
    half3 color = brdf*atten + brdfData.diffuse;
    return half4(color,dot(brdf, half3(0.3, 0.59, 0.11)));
}
half3 CustGlobalIllumination(BRDFData brdfData, half3 normalWS, half3 viewDirectionWS, half RefIntensity)
{
    half3 reflectVector = reflect(-viewDirectionWS, normalWS);
    half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));
    half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, 1.0, RefIntensity);
    return EnvironmentBRDF(brdfData, half3(0.0,0.0,0.0), indirectSpecular, fresnelTerm);
 }
half3 HairHighLight(float3 N,float3 H,float lightMask)
{
	float3 NV = mul(UNITY_MATRIX_V, N);
	float3 HV = mul(UNITY_MATRIX_V, H);
	float NdotH = dot(normalize(NV.xz), normalize(HV.xz));
	NdotH = pow(NdotH, 6) * _HighLight;
	NdotH = pow(NdotH, 1 / _HLightLength);
	float lightFeather = _HLightFeather * NdotH;
	float lightStepMax = saturate(1 - NdotH + lightFeather);
	float lightStepMin = saturate(1 - NdotH - lightFeather);
	half3 HColor = smoothstep(lightStepMin, lightStepMax, clamp(lightMask, 0, 0.99))*_HighLightColor.rgb;
	return HColor;
}
float _FaceLightOffset,_FaceLightSoftness;
float3 _Forward,_RightDir;
float PCFSample8x8(float2 uv,float RL)
{
	float shadowR,shadowL = 0;
	for (int x = -3.5; x <= 3.5; x+=1.0)
	{
		for (int y = -3.5; y <= 3.5; y+=1.0)
		{
			float3 lightMask = tex2D(_LightMaskTex, uv + float2(x, y) * 0.001);
			lightMask.gb += _FaceLightOffset;
			shadowR += lightMask.g > -RL ? _FaceLightSoftness : 0;
			shadowL += lightMask.b > RL ? _FaceLightSoftness : 0;
		}
	}
	shadowR /= 64;
	shadowL /= 64;
	return saturate(min(shadowR,shadowL));
}
float faceLight(Light light,float2 uv)
{
	float3 _Front = -normalize(_Forward.xyz);
	float3 _Right = normalize(_RightDir.xyz);
    float FL = dot(normalize(_Front.xz), normalize(light.direction.xz));
    float RL = dot(normalize(_Right.xz), normalize(light.direction.xz));
    RL = -(acos(RL)/3.14159265 - 0.5)*2;
    float faceLightRamp = (FL > 0) * PCFSample8x8(uv,RL);
	return faceLightRamp;
}
void RampResultFace(Light light, float shadowAtten,float ndhL,inout float3 final,float3 lightMask,float2 uv,float RampV,half3 WPos)
{
	float faceLightRamp = faceLight(light,uv);
	half3 ramp = tex2D(_RampTex, half2(0, RampV)).rgb*_RampColor;
	final *= lerp(ramp,1,faceLightRamp*lightMask.r*shadowAtten);
	final *= 1-lerp(0, (1 - lightMask.rrr-final.rgb) * _LightMaskBackParam, max(0, -ndhL));
}
half Atten(float NL,float3 lightMask)
{
	half lightAtten = NL;
	lightAtten = lerp(lightMask.r * lightAtten, lightAtten, _LightMaskParam+0.3);
	return lerp(lightAtten,0.9,step(0.9,lightAtten));
}
void RampResult(Light light, float shadowAtten,float ndhL,inout float3 final,float3 lightMask,float2 uv,float RampV,half3 WPos)
{
	half lightAtten = Atten(ndhL,lightMask.r);
	half2 rampUV = half2(lightAtten, RampV);
	// 采样Ramp贴图
	half4 ramp = tex2D(_RampTex, rampUV);
	// 取出纯白色值
	half rampWhiteColor = step(3, ramp.r + ramp.g + ramp.b);
	ramp.rgb = lerp(ramp.rgb * _RampColor, ramp.rgb, rampWhiteColor);
#if !defined(_RECEIVE_SHADOWS_OFF)
	ramp.rgb = lerp(ramp.rgb,RampCol(_RampTex,0, RampV),1 - shadowAtten);
#endif
	final *= ramp.rgb;
	final *= 1-lerp(0, (1 - lightMask.rrr-final.rgb) * _LightMaskBackParam, max(0, -ndhL));
}