/*------------------------------------------------------------------------------
				SKYRIM OPTICAL ENHANCEMENT by Matso
------------------------------------------------------------------------------*/

#define PI	3.1415926535897932384626433832795

/// User variables //////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bright pass parameters
extern float fLuminance = 0.4;
extern float fMiddleGray = 0.99;
extern float fWhiteCutoff = 0.89;

// Lens flare parameters
extern float4 fvScales = float4(0.33, 0.55, 0.77, 1.13);	// flares scale
extern float fPower = 2.85;		// effect blend factor
extern float fModulate = 2.465;	// bright pass luminance multiplier (the bigger, the dimmer the effect is)
extern float fGamma = 0.82;		// gamma for the effect
extern int iNumFlares = 1;		// number of flares used

// Chromatic aberration parameters
extern float3 fvChroma = float3(0.996, 1.001, 1.006);	// displacement scales of red, green and blue respectively
extern float fBaseRadius = 0.8;		// below this radius the effect is less visible
extern float fFalloffRadius = 1.8;	// over this radius the effects is maximal
extern float fChromaPower = 0.4;	// power of the effect

/// Shader code /////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define DIRECTION_NUMBER	8

const float w1 = 0.00524f;
const float2 dirs[DIRECTION_NUMBER] = {
	float2(1.0f, 0.0f),
	float2(0.707f, 0.707f),
	float2(0.0f, 1.0f),
	float2(-0.707f, 0.707f),
	float2(-1.0f, 0.0f),
	float2(-0.707f, -0.707f),
	float2(0.0f, -1.0f),
	float2(0.707f, -0.707f)
};

float3 BrightPass(float2 tex)
{
	float3 c = tex2D(s0, tex).rgb;
    float3 bC = max(c - fModulate * float3(fLuminance, fLuminance, fLuminance), 0.0f);
    float bright = dot(bC, 1.0f);
    bright = smoothstep(0.0f, 0.5f, bright);
    return lerp(0.0f, c, bright);
}

float3 BlurPass(float2 tex)
{
	float sum = 0;
	float3 c = float3(0.0, 0.0, 0.0);
	
	for (int i = 0; i < DIRECTION_NUMBER; ++i) 
	{		
		c += BrightPass(tex + dirs[i] * w1);
		sum += 1;
	}
	return (c / sum);
}

float4 LensFlare(float2 tex)
{
	float3 flareColor = float3(0.0, 0.0, 0.0);
	float2 fRefPosition = float2(0.0, 0.0);
	
	for (int i = 0; i < 4 && i < iNumFlares; ++i)
	{
		// We build the effect by appropriate scaling and tinting the bright pass texture
		float2 uv = ((tex * 2.0 - 1.0) * fvScales[i]) * 0.5 + 0.5;
		float2 _uv = ((tex * 2.0 - 1.0) * -fvScales[i]) * 0.5 + 0.5;
			
		// Tint color is given as the distance of the fragment to the optical axis (point (0.5, 0.5) in texture coordinates)
		float l = length((uv * 2.0 - 1.0)) * 2.0;
		float r = 0.5 * sin(-l * PI * 2.0) + 0.5;
		float g = 0.5 * cos(-l * PI * 2.0) + 0.5;
		float b = 0.5 * -sin(-l * PI * 2.0) + 0.5;
		
		float3 tint = float3(r, g, b);
		
		float3 flare = BlurPass(uv) * tint;
		float3 _flare = BlurPass(_uv) * tint;
			
		flareColor += flare + _flare;
	}
	flareColor = pow(flareColor, fGamma);
	
	return float4(flareColor * fPower, 1);
}

float4 ChromaticAberration(float2 tex)
{
	float d = distance(tex, float2(0.5, 0.5));
	float f = smoothstep(fBaseRadius, fFalloffRadius, d);
	float3 chroma = (f + fvChroma);
	
	float2 tr = ((2.0 * tex - 1.0) * chroma.r) * 0.5 + 0.5;
	float2 tg = ((2.0 * tex - 1.0) * chroma.g) * 0.5 + 0.5;
	float2 tb = ((2.0 * tex - 1.0) * chroma.b) * 0.5 + 0.5;
	
	float3 color = float3(tex2D(s0, tr).r, tex2D(s0, tg).g, tex2D(s0, tb).b) * (1.0 - f);
	
	return float4(color * fChromaPower, 1.0);
}

float4 OpticalEnhancement(float2 tex : TEXCOORD0, float4 color : COLOR0) : COLOR0
{
	float4 c0 = LensFlare(tex);
	float4 c1 = ChromaticAberration(tex);
    return saturate(c0 + c1);
}
