//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//

uniform sampler2D DiffSpec : TEX0;
uniform sampler2D NormGlow : TEX1;

uniform float3 v3LightPos;
uniform float3 v3CameraPos;

struct PS_INPUT
{
	float4 FrontColor		: COLOR0;
	float4 SecondaryColor	: COLOR1;
	float2 TexCoord			: TEXCOORD0;
	float4 BaseNormal		: TEXCOORD1;
};

struct PS_OUTPUT
{
	float4 Color		: COLOR;
};

PS_OUTPUT main( PS_INPUT IN )
{
	PS_OUTPUT OUT;

	float4 fDiffSpecMap = tex2D( DiffSpec, IN.TexCoord );
	float4 fBaseColor = float4( fDiffSpecMap.rgb, 1.0 );

	// Extract normals and glow from texture
	float4 fNormGlow = tex2D( NormGlow, IN.TexCoord );

	float3 vLightDirection = normalize( v3LightPos );
	float3 vNorm = IN.BaseNormal.xyz;

	float fNDotL = dot( vNorm, vLightDirection );

	float3 vReflection = normalize( ((2.0f * vNorm) * (fNDotL)) - vLightDirection );

	float3 vViewDirection = normalize( v3CameraPos );
	float fRDotV = max( 0.0f, dot( vReflection, vViewDirection ) );


	// Calculate specular component
	// Shininess is hard-coded, but a scaling is applied from the texture map
	float spec = pow( fRDotV, 25.0f ); 
	float4 fTotalSpecular = spec * fDiffSpecMap.a * fBaseColor;

	// Diffuse component, used together with scattering
	float fDiffuseC = max( 0.0f, fNDotL );
	float4 fTotalDiffuseScale = ((1.0 - fDiffuseC) * IN.SecondaryColor + fDiffuseC);

	// Calculate glow. The pow is there to provide faster fallof in the ramp area
	float4 fTotalGlow = fNormGlow.a * 1.7 * pow( 1.0 - fTotalDiffuseScale, 5.0f ) * fBaseColor;

	// Calculate base diffuse/scatter light
	float4 fTotalScatter = IN.FrontColor + fBaseColor * fTotalDiffuseScale;

	// The whole is not greater than the sum of all components
	OUT.Color = saturate( fTotalSpecular + fTotalScatter + fTotalGlow );

	return( OUT );
}
