//SA bump-shiny material. Based on NVIDIA Fx Composer example "BumpGlossed.fx",with tweaks and
//changes as necessary for SA compatability

// This is used by 3dsmax to load the correct parser
string ParamID = "0x003";

//////////////////////////////////////////////////
//Matrices
//////////////////////////////////////////////////
half4x4 WorldIT : WorldInverseTranspose < string UIWidget = "None"; >;
half4x4 WorldViewProj : WorldViewProjection < string UIWidget = "None"; >;
half4x4 World : World < string UIWidget = "None"; >;
half4x4 ViewInv : ViewInverse < string UIWidget = "None"; >;

//////////////////////////////////////////////////
//Main Light
//////////////////////////////////////////////////
half3 LightDir : Direction
<
	string Object = "Spotlight";
	string Space = "World";
> = {1.0f, -1.0f, 1.0f};

half4 LightColor1 : Diffuse <
    string UIName =  "Light1 Color";
    string Object = "Spotlight";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

//////////////////////////////////////////////////
//Material surface
//////////////////////////////////////////////////
half4 MatDiffuse : Diffuse
<
    string UIName =  "Material Diffuse";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

half4 MatAmbient : Ambient
<
    string UIName =  "Material Ambient";
    string UIWidget = "Color";
> = {0.0f, 0.0f, 0.0f, 1.0f};

half4 MatSpec : Specular
<
    string UIName =  "Material Specular";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

half MatSpecPow : SpecularPower <
    string UIWidget = "slider";
    half UIMin = 1.0;
    half UIMax = 128.0;
    half UIStep = 1.0;
    string UIName =  "specular power";
> = 40.0;

//Extra material attributes
half refmul
<
	string UIName = "Reflection Multiplier";
	string UIWidget = "slider";
	half UIMin = 0.0;
    half UIMax = 1.0;
    half UIStep = 0.01;
> = 0.5f;

//////////////////////////////////////////////////
//Textures
//////////////////////////////////////////////////

texture colorTexture : Diffuse <
    string ResourceName = "default_color.dds";
    string ResourceType = "2D";
>;

texture normalTexture : NORMAL <
    string ResourceName = "default_bump_normal.dds";
    string ResourceType = "2D";
>;

texture envTexture : ENVIRONMENT <
    string ResourceName = "default_reflection.dds";
    string ResourceType = "Cube";
>;

//////////////////////////////////////////////////
//Samplers
//////////////////////////////////////////////////

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

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

samplerCUBE envSampler = sampler_state {
	Texture = <envTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
	AddressU = clamp;
	AddressV = clamp;
	AddressW = clamp;
};

//////////////////////////////////////////////////
//Structures
//////////////////////////////////////////////////

//Vertex structre from game
struct appdata {
    half3 Position	: POSITION;
    half3 UV		: TEXCOORD0;
    half4 Normal	: NORMAL;
    half4 Tangent	: TANGENT0;
    half4 Binormal	: BINORMAL0;
};

//data passed from the vertex shader to the pixel shader
struct vertexOutput {
    half4 HPosition	: POSITION;
    half3 TexCoord	: TEXCOORD0;
    half3 LightVec1	: TEXCOORD1;
    half3 WorldNormal	: TEXCOORD2;
    half3 WorldPos	: TEXCOORD3;
    half3 WorldEyePos	: TEXCOORD4;
    half3 WorldTangent	: TEXCOORD5;
    half3 WorldBinorm	: TEXCOORD6;
};

//////////////////////////////////////////////////
//Shaders
//////////////////////////////////////////////////

//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;
    half4 Po = half4(IN.Position.xyz,1.0);
    half3 Pw = mul(Po, World).xyz;
    OUT.WorldPos = Pw;
    OUT.LightVec1 = normalize(-LightDir);
    OUT.TexCoord = IN.UV;
    OUT.WorldEyePos = ViewInv[3].xyz;
    OUT.HPosition = mul(Po, WorldViewProj);
    return OUT;
}

//Pixel Shader
half4 mainPS(vertexOutput IN) : COLOR
{
    half4 map = tex2D(colorSampler,IN.TexCoord.xy);
    half3 bumps = tex2D(normalSampler,IN.TexCoord.xy).xyz - (0.5).xxx;
    half4 specmap = saturate(tex2D(colorSampler,IN.TexCoord.xy));
    half3 Nn = normalize(IN.WorldNormal);
    half3 Tn = normalize(IN.WorldTangent);
    half3 Bn = normalize(IN.WorldBinorm);
    half3 Nb = Nn + (bumps.x * Tn + bumps.y * Bn);
    Nb = normalize(Nb);
    
    //calc light vec
    half3 Vn = normalize(IN.WorldEyePos - IN.WorldPos);
    half3 Ln = normalize(IN.LightVec1.xyz);
    half3 Hn = normalize(Vn + Ln);
    half hdn = pow(max(0,dot(Hn,Nb)),MatSpecPow) * specmap;
    half ldn = dot(Ln,Nb);
    ldn = max(0.0,ldn);
    
    //blend light colors
    half4 diffContrib = ldn * LightColor1;
    half4 specContrib = (ldn * hdn) * (LightColor1 * MatSpec);
    
    //set reflection map + UV coords
    half3 reflVect = reflect(Vn,Nb).xzy;//uv coords need to be swizzled to appear correct ingame
	half4 reflColor = texCUBE(envSampler,-reflVect);
	
	half4 result = (map * MatDiffuse) * (diffContrib + MatAmbient) + (specContrib + ((refmul * specmap) * reflColor));     
	result.a = MatDiffuse.a * map.a;
	
    return result;
}

//////////////////////////////////////////////////
//Technique
//////////////////////////////////////////////////

technique Bumpref
{
	pass p0
	{
		AlphaBlendEnable = TRUE;
		AlphaTestEnable = TRUE;
		AlphaFunc = Greater;
		AlphaRef = 0x01;
		SrcBlend = 5;
		DestBlend = 6;
		cullmode = CW;
		VertexShader = compile vs_2_0 mainVS();
		PixelShader = compile ps_2_a mainPS();
	}
}