/*********************************************************************NVMH3****
Path:  NVSDK\Common\media\cgfx1.4
File:  metal.cgfx

Copyright NVIDIA Corporation 2002
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


Comments:
	$Id: //sw/devrel/SDK/MEDIA/CgFX1.4/metal.cgfx#9 $

******************************************************************************/

float4x4 WorldIT : WorldInverseTranspose;
float4x4 WorldViewProj : WorldViewProjection;
float4x4 World : World;
float4x4 ViewI : ViewInverse;

float4 LightPos : Position 
<
	string UIName =  "Lamp Position";
	string Object = "PointLight";
	string Space = "World";
> = {-54.0f, 50.0f, 100.0f, 1.0f};

float3 LightColor : Diffuse
<
	string UIName =  "Lamp";
	string UIWidget = "Color";
	string Object = "PointLight";
> = {1.0f, 1.0f, 1.0f};

float3 AmbiColor : Ambient 
<
	string UIName =  "Ambient Light";
	string UIWidget = "Color";
> = {0.07f, 0.07f, 0.07f};

float3 SurfColor : Diffuse 
<
	string UIName =  "Surface";
	string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f};

float SpecExpon : SpecularPower
<
	string UIName =  "specular power";
	string UIWidget = "Slider";
	float UIMin = 1.0;
	float UIMax = 128.0;
	float UIStep = 1.0;
> = 25.0;

float Kd 
<
	string UIName =  "Diffuse (from dirt)";
	string UIWidget = "Slider";
	float UIMin = 0.0;
	float UIMax = 1.0;
	float UIStep = 0.05;
> = 0.1;

texture ColorTexture : Diffuse
<
	string ResourceName = "default_color.dds";
	string ResourceType = "2D";
	string UIName =  "Surface Texture (if used)";
>;

sampler2D ColorSampler = sampler_state 
{
	Texture = <ColorTexture>;
	MinFilter = LinearMipMapLinear;
	MagFilter = Linear;
};

struct appdata 
{
	float3 Position	: POSITION;
	float4 UV				: TEXCOORD0;
	float4 Normal		: NORMAL;
};

struct vertexOutput 
{
	float4 HPosition		: POSITION;
	float4 TexCoord			: TEXCOORD0;
	float3 LightVec			: TEXCOORD1;
	float3 WorldNormal	: TEXCOORD2;
	float3 WorldView		: TEXCOORD5;
};

struct vertexOutputPS1 
{
	float4 HPosition	: POSITION;
	float4 TexCoord0	: TEXCOORD0;
	float4 diffCol		: COLOR0;
	float4 specCol		: COLOR1;
};

vertexOutput mainVS(appdata IN) 
{
    vertexOutput OUT;
    float4 normal = normalize(IN.Normal);
    OUT.WorldNormal = mul(WorldIT, normal).xyz;
    float4 Po = float4(IN.Position.xyz,1);
    float3 Pw = mul(World, Po).xyz;
    OUT.LightVec = normalize(LightPos - Pw);
    OUT.TexCoord = IN.UV;
    OUT.WorldView = normalize(ViewI[3].xyz - Pw);
    OUT.HPosition = mul(WorldViewProj, Po);
    return OUT;
}

vertexOutputPS1 metalPVS(appdata IN)
{
    vertexOutputPS1 OUT;
    float3 Nn = normalize(mul(WorldIT, IN.Normal).xyz);
    float4 Po = float4(IN.Position.xyz,1);
    float3 Pw = mul(World, Po).xyz;
    float3 Ln = normalize(LightPos - Pw);
    float ldn = dot(Ln,Nn);
    float diffComp = max(0,ldn) * Kd;
    OUT.diffCol = float4((SurfColor*(diffComp*LightColor+AmbiColor)),1);
    OUT.TexCoord0 = IN.UV;
    float3 Vn = normalize(ViewI[3].xyz - Pw);
    float3 Hn = normalize(Vn + Ln);
    float hdn = pow(max(0,dot(Hn,Nn)),SpecExpon);
    OUT.specCol = float4((hdn * LightColor * SurfColor),1);
    OUT.HPosition = mul(WorldViewProj, Po);
    return OUT;
}

float4 metalPPS(vertexOutputPS1 IN) : COLOR
{
	return (IN.diffCol + tex2D(ColorSampler,IN.TexCoord0.xy) * IN.specCol);
}

void metal_shared(vertexOutput IN,
			out float3 DiffuseContrib,
			out float3 SpecularContrib)
{
    float3 Ln = normalize(IN.LightVec);
    float3 Nn = normalize(IN.WorldNormal);
    float3 Vn = normalize(IN.WorldView);
    float3 Hn = normalize(Vn + Ln);
    float4 litV = lit(dot(Ln,Nn),dot(Hn,Nn),SpecExpon);
    DiffuseContrib = litV.y * Kd * LightColor + AmbiColor;
    SpecularContrib = litV.z * LightColor;
}

float4 metalPS(vertexOutput IN) : COLOR 
{
	float3 diffContrib;
	float3 specContrib;
	metal_shared(IN,diffContrib,specContrib);
	float3 result = diffContrib + (SurfColor * specContrib);
	return float4(result,1);
}

float4 metalPS_t(vertexOutput IN) : COLOR 
{
	float3 diffContrib;
	float3 specContrib;
	metal_shared(IN,diffContrib,specContrib);
	float3 map = tex2D(ColorSampler,IN.TexCoord.xy).xyz;
	float3 result = diffContrib + (SurfColor * map * specContrib);
	return float4(result,1);
}

/*************/
  
technique TexturedVS < string Script = "Pass=p0;"; > 
{
	pass p0 < string Script = "Draw=geometry;"; > 
	{
		VertexProgram = compile arbvp1 metalPVS();
		DepthTestEnable = true;
		DepthMask = true;
		CullFaceEnable = false;
		FragmentProgram = compile arbfp1 metalPPS();
	}
}

technique UntexturedPS < string Script = "Pass=p0;"; > 
{
	pass p0 < string Script = "Draw=geometry;"; > 
	{
		VertexProgram = compile arbvp1 mainVS();
		DepthFunc = LEqual;
		FragmentProgram = compile arbfp1 metalPS();
	}
}

technique TexturedPS < string Script = "Pass=p0;"; > 
{
	pass p0 < string Script = "Draw=geometry;"; > 
	{
		VertexProgram = compile arbvp1 mainVS();
		DepthTestEnable = true;
		DepthMask = true;
		CullFaceEnable = false;
		FragmentProgram = compile arbfp1 metalPS_t();
	}
}

