//Shader code by Mark Blosser
//WEBSITE:  www.hyrumark.com
//EMAIL:  mark@hyrumark.com

//Description:  Shader for static entities with lightmapping, and specular "hero" highlights that always face player.
//Textures: 
//"texture_D.dds"      diffuse texture
//"texture_I.dd"       specular texture
//"texture_N.dds"       specular texture (might need both I and N for this to work, have to do more digging)

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

float4x4 World      : WORLD;

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



/******TWEAKABLES***************************/

float SpecExpon : Power
<
    string UIWidget = "slider";
    float UIMin = 1.0;
    float UIMax = 128.0;
    float UIStep = 1.0;
    string UIName =  "specular power";
> = 64.0;


/******VALUES PULLED FROM FPSC - NON TWEAKABLE**********/

float4 AmbiColor : Ambient
<
    string UIName =  "Ambient Light Color";
> = {0.1f, 0.1f, 0.1f, 1.0f};

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

float4 LightSource
<
    string UIType = "Fixed Light Source";
> = {500000.0f,50000.0f, -0.0f, 1.0f};




/****************** TEXTURES AND SAMPLERS*********************/

texture LightMap : DiffuseMap
<
    string Name = "LM.tga";
    string type = "2D";
>;

texture DiffuseMap : DiffuseMap
<
    string Name = "D.tga";
    string type = "2D";
>;

//could be anything here - ill,spec,normal,cube
texture EffectMap : DiffuseMap
<
    string Name = "N.tga";
    string type = "2D";
>;





//Lightmap texture
sampler2D LightmapSampler = sampler_state
{
    Texture   = <LightMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

//Diffuse Texture _D
sampler2D DiffuseSampler = sampler_state
{
    Texture   = <DiffuseMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

//Effect Texture _I (could be anything here - ill,spec,normal,cube)
sampler2D EffectSampler = sampler_state
{
    Texture   = <EffectMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};


;





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

struct appdata {
    float4 Position	: POSITION;
    float4 UV0		: TEXCOORD0;
    float4 UV1		: TEXCOORD1;
    float4 Normal	: NORMAL;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;
};



/*data passed to pixel shader*/
struct vertexOutput
{
    float4 Position    : POSITION;
    float2 TexCoord     : TEXCOORD0;
    float2 TexCoordLM   : TEXCOORD1;
    float3 LightVec	    : TEXCOORD2;
    float3 WorldNormal	: TEXCOORD3;
    float4 WPos : TEXCOORD4;
};


/*******Vertex Shader***************************/

vertexOutput mainVS(appdata IN)   
{
    
	vertexOutput OUT;
    
    //float4 tempPos = float4(IN.Position, 1);
    float4 worldSpacePos = mul(IN.Position, World);
    
    OUT.WorldNormal = normalize(mul(IN.Normal, WorldIT).xyz);
    OUT.LightVec = normalize (LightSource - worldSpacePos );
    OUT.Position = mul(IN.Position, WorldViewProj);
    OUT.TexCoord  = IN.UV0; 
    OUT.TexCoordLM  = IN.UV1; 
    OUT.WPos =   worldSpacePos;                                                                        
                                           

    return OUT;
}


/****************Framgent Shader*****************/

float4 mainPS(vertexOutput IN) : COLOR
{
    float4 LM = tex2D(LightmapSampler,IN.TexCoordLM);  //sample lightmap texture
    float4 diffuse = tex2D(DiffuseSampler,IN.TexCoord.xy);    //sample diffuse texture    
    float4 effectmap = tex2D(EffectSampler,IN.TexCoord.xy);    //sample specular map texture 
    
    float3 Ln = (IN.LightVec);
    float3 Nn = normalize(IN.WorldNormal);  //must be normalized here for correct curved surface spec!
    
    //calculate distance attenuation value based on eye position
	//float dis = distance(IN.WPos,eyePos);
	//float atten = 1/(dis*.01*dis*.05+dis*.01);
	//float atten = (1/(dis*(0.5*dis)*.2+dis))*4000;
	//atten = clamp(atten,0,1.5);  //second value controls how bright to let the highlights become

   
     
    
    //non-normalized view vector for constant forward "hero" spec
    float3 V  = (eyePos - IN.WPos);
	
        
    //half vector
    float3 Hn = normalize(V+Ln);
    
    
   //specular highlights 
    float herospec = pow(max(dot(Nn,Hn),0),64);
    
    
    //multiply spec texture, lightmap, and diffuse texture
    float4 specular = (herospec)*(LM+0.1)*effectmap*SurfColor;
    
        
    
    float4 LMfinal = (LM+0.05 + AmbiColor)*diffuse  ;
    
        
    float4 result =   LMfinal  +(specular)  ;
    
    
    return result;
}


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

technique dx9textured
{
    pass P0
    {
        // 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 mainPS();
    }
}
