// Per-Pixel diffuse lighting

float4x4	worldMatrix				: World;
float4x4 	worldViewProjMatrix 	: WorldViewProjection;
float4x4	vpMatrix 				: ViewProjection;
float4x4	viewMatrix				: View;
float4 		lightPos				: Light0;
float3		viewPos					: ViewPos;
float3		viewDirection			: ViewDir;
float2		screenSize				: Screen;
float4x4	camera					: Camera;
float3		godLightDir;
float		time					: Time;
float3		mieParams = float3( 1-0.25f, 1+0.25f, 2*0.5f );
float		rayLength = 17.0f;
float		spacing = 0.5f;
float3		diffuseColor
<
	string UIName = "Diffuse Material Color";
> = { 1.0f, 1.0f, 1.0f };

float3		ambientColor
<
	string UIName = "Ambient Material Color";
> = { 0.0f, 0.0f, 0.0f };
texture texture_0;
sampler2D texture_0Sampler = sampler_state 
{
    texture = <texture_0>;
    AddressU  = CLAMP;        
    AddressV  = CLAMP;
    AddressW  = CLAMP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

struct VertexInput {
    float3 Position	: POSITION;
};

struct VertexOutput
{
    float4 HPosition	: POSITION;
    float intensity		: TEXCOORD2;
};

float Fresnel( float3 I, float3 N, float R0 )
{
	return R0 + (1.0f-R0)*pow(1-dot(I,N),5);
}

VertexOutput VS_God(VertexInput IN) {
    VertexOutput OUT;
    
    IN.Position = IN.Position*float3(spacing,spacing,1.0f);
    float3 worldPos = mul(float4(IN.Position,1.0f), worldMatrix);
    
    float animValue = sin(length(IN.Position)+time)*0.5f;
    float3 Normal = float3(sin(animValue),cos(animValue*0.5f),cos(animValue));
    float3 worldNormal = mul(Normal, worldMatrix); 
    worldNormal = normalize(worldNormal);
    
	float3 lightDir = normalize(worldPos-lightPos);
    float3 T = -refract(lightDir,worldNormal,1/1.3333f);
    float tr = 1.0f-Fresnel(-lightDir,worldNormal, 0.0204f);
    
    worldPos += IN.Position.z*T*rayLength;
    
    float totalDist = abs((IN.Position.z+0.1f)*rayLength)*3.0f+length(worldPos - viewPos)*0.5f;
    OUT.intensity = exp(-totalDist*0.4f)*tr*1.0f;
    OUT.HPosition = mul(float4(worldPos,1.0f), vpMatrix);
    return OUT;
}

float4 PS_God( VertexOutput IN ) : COLOR
{
	return float4(float3(IN.intensity.xxx),1.0f);
}

technique ps20<bool quad=true; string material="godRays";>
{
    pass p0
    {		
		VertexShader = compile vs_1_1 VS_God();
		PixelShader = compile ps_2_0 PS_God();
		
		CullMode= none;
		ZWriteEnable = false;
		ZEnable = false;
		
		AlphaBlendEnable = true;
		srcBlend = srcAlpha;
		destBlend = one;
    }
}


struct VertexInput_final 
{
    float3 Position	: POSITION;
    float2 uvCoords	: TEXCOORD0;
};

struct VertexOutput_final
{
    float4 Position	: POSITION;
    float4 uv[2]	: TEXCOORD0;
    float3 viewDir  : TEXCOORD2;
};

VertexOutput_final VS_Final(VertexInput_final IN) {
    VertexOutput_final OUT;
    OUT.Position = float4(IN.Position,1.0f);
    OUT.uv[0] = float4(IN.uvCoords.x, IN.uvCoords.y, IN.uvCoords.x + (4.0f/screenSize.x), IN.uvCoords.y);
    OUT.uv[1] = float4(IN.uvCoords.x + (4.0f/screenSize.x), IN.uvCoords.y + (4.0f/screenSize.y), IN.uvCoords.x, IN.uvCoords.y + (4.0f/screenSize.y));
    float3 viewDir = IN.Position-float3(0.0f,0.0f,-2.0f);
    OUT.viewDir = normalize(mul(viewDir,camera));
    //OUT.Position += float4(OUT.viewDir*2.0f,0.0f);
    return OUT;
}

float ComputeMie(float3 viewDir, float3 sunDir) 
{
	float den = (mieParams.y-mieParams.z*dot(sunDir,viewDir));	
	den = rsqrt(den);
	float phase = mieParams.x*(den*den*den);
	return phase;
}

float4 PS_Final( VertexOutput_final IN ) : COLOR
{
	float shaft = 0.0f;
	for( int i = 0; i < 2; i++ )
	{
		shaft += tex2D(texture_0Sampler, IN.uv[i].xy);
		shaft += tex2D(texture_0Sampler, IN.uv[i].zw);
	}
	float3 viewDir = normalize(IN.viewDir);
	float phase = ComputeMie(-viewDir, godLightDir);
	float godRays = (0.15f+shaft)*phase;
	return float4(1.0f,1.0f,1.0f,godRays*0.3f);
}


technique finalStep
{
	pass p0
	{
		VertexShader = compile vs_1_1 VS_Final();
		PixelShader = compile ps_2_0 PS_Final();
		
		ZWriteEnable = false;
		ZEnable = false;
		AlphaBlendEnable = true;
		SrcBlend = srcAlpha;
		DestBlend = one;
	}
}