//
// Bump + Diffuse + ( Cube * Reflect )
//

/************* UNTWEAKABLES **************/

float4x4 WorldIT : WorldInverseTranspose;
float4x4 WorldViewProj : WorldViewProjection;
float4x4 World : World;
float4x4 ViewInv : ViewInverse;
float4 eyePos : CameraPosition;

float3 RenderColor = { 0.000000, 0.000000, 0.000000 };

float4 SpotFlashPos;


float4 SpotFlashColor;


float SpotFlashRange   //fixed value that FPSC uses
<
    string UIName =  "SpotFlash Range";
    
> = {600.00};




/************* SURFACE **************/

float4 LightSource
<
    string UIType = "Light Source";
> = { -580.000000, 100.000000, -750.000000, 0.000000 };

float4 AmbiColor : Ambient
<
    string UIName =  "Ambient Light Color";
> = { 0.100000, 0.100000, 0.100000, 1.000000 };

float4 SurfColor : Diffuse
<
    string UIName =  "Surface Color";
    string UIType = "Color";
> = { 1.000000, 1.000000, 1.000000, 1.000000 };

float Bumpy
<
    string UIType = "slider";
    float UIMin = 0.0;
    float UIMax = 10.0;
    float UIStep = 0.1;
    string UIName =  "bump power";
> = 5.000000;


float Alphavalue : AlphaOverride
<
    string UIName =  "Alpha Override";
> = 1.0f;


/************* TEXTURES **************/

texture colorTexture : DiffuseMap
<
    string Name = "default_colorandalpha.dds";
    string type = "2D";
 string ResourceName = ""; >;

texture normalTexture : DiffuseMap
<
    string Name = "default_bump_normal.dds";
    string type = "2D";
 string ResourceName = ""; >;

texture reflectMap : ReflectMap
<
	string Name = "default_mask.dds";
    string type = "2D";
 string ResourceName = ""; >;

texture cubeMap : EnvMap
<
	string Name = "default_cube.dds";
	string type = "Cube";
 string ResourceName = ""; >;

sampler2D colorSampler = sampler_state
{
	Texture = <colorTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler2D normalSampler = sampler_state
{
	Texture = <normalTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler2D reflectSampler = sampler_state
{
	Texture = <reflectMap>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

samplerCUBE envMapSampler = sampler_state
{
	Texture = <cubeMap>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

/************* DATA STRUCTS **************/

/* data from application vertex buffer */
struct appdata {
    float3 Position	: POSITION;
    float4 UV		: TEXCOORD0;
    float4 Normal	: NORMAL;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;
};

/* data passed from vertex shader to pixel shader */
struct vertexOutput {
    float4 HPosition	: POSITION;
    float4 TexCoord	: TEXCOORD0;
    float3 LightVec	: TEXCOORD1;
    float3 WorldNormal	: TEXCOORD2;
    float3 WorldEyeVec	: TEXCOORD3;
    float3 WorldTangent	: TEXCOORD4;
    float3 WorldBinorm	: TEXCOORD5;
    float3 worldSpacePos	: TEXCOORD6;
};

/*********** vertex shader ******/

vertexOutput mainVS(appdata IN)
{
    vertexOutput OUT;
    OUT.WorldNormal = mul(IN.Normal, WorldIT).xyz;
    OUT.WorldTangent = mul(IN.Tangent, WorldIT).xyz;
    OUT.WorldBinorm = mul(IN.Binormal, WorldIT).xyz;
    float4 tempPos = float4(IN.Position.x,IN.Position.y,IN.Position.z,1.0);
    float3 worldSpacePos = mul(tempPos, World).xyz;
    OUT.LightVec = LightSource - worldSpacePos;
    OUT.TexCoord = IN.UV;
    OUT.WorldEyeVec = normalize(ViewInv[3].xyz - worldSpacePos);
    OUT.HPosition = mul(tempPos, WorldViewProj);
    OUT.worldSpacePos = mul(tempPos, World).xyz;
    return OUT;
}

/********* pixel shader ********/


float4 CalcSpotFlash( float3 worldNormal, float3 worldPos )
{
    float4 output = (float4)0.0;
    float3 toLight = SpotFlashPos.xyz - worldPos.xyz;
    float3 lightDir = normalize( toLight );
    float lightDist = length( toLight );
    
    float MinFalloff = 200;  //falloff start distance - 50,0,.01 are very cool too for lanterns
    float LinearFalloff = 1;
    float ExpFalloff = .005;  // 1/200
    
    float fAtten = 1.0/(MinFalloff + (LinearFalloff*lightDist)+(ExpFalloff*lightDist*lightDist));
    
    SpotFlashPos.w = clamp(0,1,SpotFlashPos.w -.2);
    
    
    output += max(0,dot( lightDir, worldNormal ) * 1*SpotFlashColor*fAtten * (SpotFlashPos.w) );
    
    return output;
}

float4 mainPS2(vertexOutput IN) : COLOR
{
    // all shaders should receive the clip value                                                   
    
    float4 diffusemap = tex2D(colorSampler,IN.TexCoord.xy);
    float4 specmap = tex2D(reflectSampler,IN.TexCoord.xy);
    

    float4 normalmap = tex2D(normalSampler,IN.TexCoord.xy); //sample normal map
    //normalmap.xyzw = normalmap.wyxx;  //swizzle for quality DXT5nm normal map format
    normalmap.xyz = normalmap.xyz *2 -1;  //expand normal map 
    float3 Ln = normalize(IN.LightVec);
    float3 Nn = (IN.WorldNormal);
    float3 Tn = (IN.WorldTangent);
    float3 Bn = (IN.WorldBinorm);
    float3 Nb =  (normalmap.z * Nn) + (1.0*(normalmap.x * Tn + normalmap.y * Bn));
    Nb = normalize(Nb);
    float3 Vn = normalize(IN.WorldEyeVec);
    float3 Hn = normalize(Vn + Ln);
    
    //Main lighting equation 
    float4 lighting3 = lit(pow(0.5*(dot(Ln,Nb))+0.5,1.25),dot(Hn,Nb),32);       
    float4 lighting2 = lit(pow(0.5*(dot(Ln,Nb))+0.5,2),dot(Hn,Nb),12);
    float4 lighting = lit((dot(Ln,Nb)),dot(Hn,Nb),32); 
    float4 ldn = dot(Ln,Nb);
    float4 diffComp = max(0,ldn);
    float4 Diffuse = diffComp ;
    float4 SurfColor2 = pow(SurfColor,10)/5;
    float4 subLamb = smoothstep(-0.2-SurfColor2,1.0,ldn) - smoothstep(0.0,1.0,ldn);
    subLamb = max(0,subLamb);
    float4 Subsurface = (subLamb * (diffusemap-((diffusemap.b+diffusemap.g)/2)));
    //Subsurface = (subLamb * illummap);

	//calculate the angle between the normal and the camera
	float4 angle = saturate( dot( Nb, IN.WorldEyeVec ) );
	
	//limit the angle
	angle = smoothstep(0.75*(1-specmap.r) , 0, angle );
	
	//use this value to produce a color
	float4 fresnel = lerp( float4(0.75,0.75,0.75,0), float4( 0.0,0.0,0.0,0), angle );
	fresnel= (1-fresnel);

    float3 G = normalize(2 * dot(Nb, Ln) * Nb - Ln);                // glance vector (view space)
    float3 Reflection = float3(G.x, G.y, G.z);
    float4 reflColor = texCUBE(envMapSampler,Reflection);
    float4 reflContrib = pow(reflColor,5*(1-specmap))*2*(specmap*specmap*specmap)*fresnel;
    float4 diffContrib = diffusemap * (lighting.y + (2.5*Subsurface)) * (SurfColor);
    float4 specContrib =(lighting.z+lighting2.z) * specmap*(SurfColor);
    specContrib = (fresnel*2*specContrib)+reflContrib;


    float4 spotflashlighting = CalcSpotFlash ( IN.WorldNormal, IN.worldSpacePos.xyz ); 




    float4 sky = lerp(SurfColor, (lighting3.y+SurfColor)/1.5, 2*Nb.g); 
    
    //float4 ambContrib =   (AmbiColor*herolightfinal);
    float4 ambContrib =  ( AmbiColor*(2*sky+AmbiColor)+spotflashlighting)*diffusemap;
    		

    float4 result = diffContrib + 2*specContrib + ambContrib  ;
    //result =0;
    result.a= diffusemap.a * Alphavalue;

    return result;
}

   float4 PS_RenderColor(vertexOutput IN)  : COLOR
     {
	return float4(RenderColor,tex2D(colorSampler,IN.TexCoord.xy).w);
     }

/****** technique *******/

technique dx9textured
{
	pass p0 
	{		
	        // lighting
	        Lighting       = FALSE;
	        SpecularEnable = FALSE;
	        FogEnable      = FALSE;

		// same vertex shader for both DX9 techniques
		VertexShader = compile vs_2_0 mainVS();
		ZEnable = true;
		ZWriteEnable = true;
		CullMode = None;
		PixelShader = compile ps_2_b mainPS2();
	}
}
   technique RenderColor
      {
 	pass p1
      {		
        // lighting
        Lighting       = FALSE;
        FogEnable      = FALSE;

        // samplers
        //Sampler[0] = (LightmapSampler);
        //Sampler[1] = (DiffuseSampler);
        //Sampler[2] = (IllSpecSampler);
		//Sampler[3] = (NormalSampler);

        // shaders
        VertexShader = compile vs_2_0 mainVS();
 	pixelShader  = compile ps_2_0 PS_RenderColor();

      }
      }     

/***************************** eof ***/


