// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

// Character skin shader
// Includes falloff shadow

#define ENABLE_CAST_SHADOWS

// Material parameters
float4 _Color;
float4 _ShadowColor;
float4 _LightColor0;
float4 _MainTex_ST;

// Textures
sampler2D _MainTex;
sampler2D _FalloffSampler;
sampler2D _RimLightSampler;

// Constants
#define FALLOFF_POWER 1.0

#ifdef ENABLE_CAST_SHADOWS

// Structure from vertex shader to fragment shader
struct v2f
{
	float4 pos    : SV_POSITION;
	LIGHTING_COORDS( 0, 1 )
	float3 normal : TEXCOORD2;
	float2 uv     : TEXCOORD3;
	float3 eyeDir : TEXCOORD4;
	float3 lightDir : TEXCOORD5;
};

#else
	
// Structure from vertex shader to fragment shader
struct v2f
{
	float4 pos    : SV_POSITION;
	float3 normal : TEXCOORD0;
	float2 uv     : TEXCOORD1;
	float3 eyeDir : TEXCOORD2;
	float3 lightDir : TEXCOORD3;
};
	
#endif

// Float types
#define float_t  half
#define float2_t half2
#define float3_t half3
#define float4_t half4

// Vertex shader
v2f vert( appdata_base v )
{
	v2f o;
	o.pos = UnityObjectToClipPos( v.vertex );
	o.uv = TRANSFORM_TEX( v.texcoord.xy, _MainTex );
	o.normal = normalize( mul( unity_ObjectToWorld, float4_t( v.normal, 0 ) ).xyz );
	
	// Eye direction vector
	float4_t worldPos =  mul( unity_ObjectToWorld, v.vertex );
	o.eyeDir = normalize( _WorldSpaceCameraPos - worldPos );

	o.lightDir = WorldSpaceLightDir( v.vertex );

#ifdef ENABLE_CAST_SHADOWS
	TRANSFER_VERTEX_TO_FRAGMENT( o );
#endif

	return o;
}

// Fragment shader
float4 frag( v2f i ) : COLOR
{
	float4_t diffSamplerColor = tex2D( _MainTex, i.uv );

	// Falloff. Convert the angle between the normal and the camera direction into a lookup for the gradient
	float_t normalDotEye = dot( i.normal, i.eyeDir );
	float_t falloffU = clamp( 1 - abs( normalDotEye ), 0.02, 0.98 );
	float4_t falloffSamplerColor = FALLOFF_POWER * tex2D( _FalloffSampler, float2( falloffU, 0.25f ) );
	float3_t combinedColor = lerp( diffSamplerColor.rgb, falloffSamplerColor.rgb * diffSamplerColor.rgb, falloffSamplerColor.a );

	// Rimlight
	float_t rimlightDot = saturate( 0.5 * ( dot( i.normal, i.lightDir ) + 1.0 ) );
	falloffU = saturate( rimlightDot * falloffU );
	//falloffU = saturate( ( rimlightDot * falloffU - 0.5 ) * 32.0 );
	falloffU = tex2D( _RimLightSampler, float2( falloffU, 0.25f ) ).r;
	float3_t lightColor = diffSamplerColor.rgb * 0.5; // * 2.0;
	combinedColor += falloffU * lightColor;

#ifdef ENABLE_CAST_SHADOWS
	// Cast shadows
	float3_t shadowColor = _ShadowColor.rgb * combinedColor;
	float_t attenuation = saturate( 2.0 * LIGHT_ATTENUATION( i ) - 1.0 );
	combinedColor = lerp( shadowColor, combinedColor, attenuation );
#endif

	return float4_t( combinedColor, diffSamplerColor.a ) * _Color * _LightColor0;
}
