float4x4 worldViewProj : WorldViewProjection;
float4x4 viewProj : ViewProjection;
float4x4 world : World;

#define BONEMODE_4x3 1

#include "generic.fx"
#include "mrt.fx"
#include "GameLights.fx"


texture diffuseTexture : DiffuseTexture;
sampler DiffuseTextureSampler = sampler_state 
{
    texture = <diffuseTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture bumpTexture : BumpTexture;
sampler BumpTextureSampler = sampler_state 
{
    texture = <bumpTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

textureCUBE envTexture : EnvironmentTexture;
samplerCUBE EnvTextureSampler = sampler_state 
{
    texture = <envTexture>;
    AddressU  = CLAMP;        
    AddressV  = CLAMP;
    AddressW  = CLAMP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture envMaskTexture : envMaskTexture;
sampler EnvMaskTextureSampler = sampler_state 
{
    texture = <envMaskTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};



texture opacityTexture : EmissiveMaskTexture;
sampler OpacityTextureSampler = sampler_state 
{
    texture = <opacityTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};



float3 campos : CAMERAPOS;

struct vertexInputBoned {
    float4 position				: POSITION;
    float3 normal				: NORMAL;
    float2 texCoordDiffuse		: TEXCOORD0;
    float4 boneids              : BLENDINDICES;
    float4 boneweights          : BLENDWEIGHT;
    float4 tangent              : TANGENT;
};

struct vertexInputUnboned {
    float4 position				: POSITION;
    float3 normal				: NORMAL;
    float2 texCoordDiffuse		: TEXCOORD0;
    float4 tangent              : TANGENT;
};

struct vertexInputBatched {
    float4 position				: POSITION;
    float3 normal				: NORMAL;
    float2 texCoordDiffuse		: TEXCOORD0;
    float4 tangent              : TANGENT;
    float batchid               : BLENDINDICES;
};

struct vertexOutput {
    float4 hPosition		: POSITION;
    half2 texCoordDiffuse	: TEXCOORD0;
#if PerVertexPreference    
	half4 diffColor			: COLOR0;
#else
    half3 ref              : TEXCOORD1;
    half3 normWorld        : TEXCOORD2;
    half3 tanWorld         : TEXCOORD3;
    half3 bitanWorld       : TEXCOORD4;
    float dist		: TEXCOORD5;
#endif
};

vertexOutput VS_Shared(float4 pos, float3 norm, float3 tang, float tangw, float2 uv)
{
    vertexOutput OUT;

#if PerVertexPreference    
	
	float3 colorSum = 0;
    float3 specularSum = 0;
    float3 eyeVecW = campos - pos.xyz;
	AddLights(norm, pos, colorSum, matSettings.Specular_Power.w, eyeVecW, specularSum);
    colorSum += matSettings.Ambient + ambientLevel;
    OUT.diffColor = float4(colorSum,1);
#else
	
    OUT.normWorld = norm;
    OUT.tanWorld = tang;
    OUT.bitanWorld = cross(norm, tang) * tangw;
    
    float3 eyeVecW = campos - pos.xyz;
    float3 reflection = reflect(-eyeVecW, norm);
	OUT.ref = reflection;
    
    OUT.dist = length( pos/100000- campos/100000 );   
#endif

    OUT.texCoordDiffuse = uv;
    OUT.hPosition = mul( pos , viewProj);
 
    return OUT;
}

vertexOutput VS_TransformBoned(vertexInputBoned IN) 
{
    float4 pos;
	float3 norm;
    float3 tang;
    
    float weight4;
    weight4 = 1 - dot(IN.boneweights.xyz, float3(1,1,1));
    float4 weights = float4(IN.boneweights.xyz, weight4);
    
    float4 boneids = VS_ScaleBoneIDsFromD3DCOLOR(IN.boneids);
    VS_TransformBonesPNT_4(IN.position, pos, IN.normal, norm, IN.tangent, tang, boneids, weights, world);
    
    return VS_Shared(pos, norm, tang, IN.tangent.w, IN.texCoordDiffuse);
}

vertexOutput VS_TransformUnboned(vertexInputUnboned IN) 
{
    float4 pos;
    float3 norm;
    float3 tang;
    
    pos = mul(IN.position, world);
    norm = mul(IN.normal, world);
    tang = mul(IN.tangent.xyz, world);
    
    return VS_Shared(pos, norm, tang, IN.tangent.w, IN.texCoordDiffuse);
}


vertexOutput VS_TransformBatchedSM1(vertexInputBatched IN) 
{
    float4 pos;
    float3 norm;
    float3 tang;
    
    pos = mul(IN.position, world);
    norm = mul(IN.normal, world);
    tang = mul(IN.tangent.xyz, world);
    
    VS_TransformBonesPNT_1_NoWorld(IN.position, pos, IN.normal, norm, IN.tangent, tang, VS_ScaleBatchID(IN.batchid));
  
  	return VS_Shared(pos, norm, tang, IN.tangent.w, IN.texCoordDiffuse);  
}

PS_OUTPUT PS_Textured( vertexOutput IN)
{
	half4 outColor;
 	PS_OUTPUT Out;
	
	half4 diffuseTexture = tex2D( DiffuseTextureSampler, IN.texCoordDiffuse );
    half4 envMask = tex2D ( EnvMaskTextureSampler, IN.texCoordDiffuse );

#if PerVertexPreference 

	// env mask too dark!
	outColor = IN.diffColor * diffuseTexture; //  * envMask;	
	SetPSOutput( Out, outColor, float4( 0, 0, 0, 1) );
  
#else

  	half4 opacity = tex2D ( OpacityTextureSampler, IN.texCoordDiffuse );
	
	half3x3 tanmat;
	tanmat[0] = normalize(IN.tanWorld);
	tanmat[2] = normalize(IN.normWorld);
	tanmat[1] = normalize(IN.bitanWorld);

    half4 normalTexture = tex2D( BumpTextureSampler, IN.texCoordDiffuse ) * 2 - 1;
    half3 normalWorld = mul(normalTexture.xyz, tanmat);
    normalWorld = normalize(normalWorld);

    half4 envTex = texCUBE(EnvTextureSampler, IN.ref);

    half3 colorSum = 0;
    half3 specularSum = 0;
	AddLights(normalWorld, 0, colorSum, matSettings.Specular_Power.w, 0, specularSum);
	
	// Light passing through
	half3 negativeWorld = normalWorld; // already negated
	half ldN = dot(dirLights[0].Direction.xyz, negativeWorld);
	half negContrib = saturate( ldN );
	
	half3 colorPassthrough = float3( 0.31, 1.0, 0.9 );
	//passthrough = 0.0f;
	negContrib = 0.2f + negContrib * 0.8f;
	colorSum += colorPassthrough * opacity.xxxx * negContrib * 2.0f;
	
  
#ifdef MAX_LIGHTING
    colorSum += matSettings.Ambient * ambientLevel;
    outColor = matSettings.Diffuse_Opacity * diffuseTexture;
    outColor.xyz *= colorSum;
    outColor.xyz += specularSum * matSettings.Specular_Power.xyz * envMask.xyz;
    outColor.xyz += matSettings.Emissive + envTex.xyz * envMask.xyz;
#else
    colorSum += matSettings.Ambient + ambientLevel;
    outColor = matSettings.Diffuse_Opacity * diffuseTexture;
    outColor.xyz *= colorSum;
    outColor.xyz += specularSum * matSettings.Specular_Power.xyz * envMask.xyz;
    outColor.xyz += matSettings.Emissive + envMask.xyz * envTex.xyz * 2.5;
#endif
    
    // Output distance in 2nd RT: .z
	SetPSOutput( Out, outColor, float4( 0, 0, IN.dist, 1) );
  
#endif
      return Out;
}



//-----------------------------------
technique boned
{
    pass p0 
    {		
		VertexShader = compile vs_2_0 VS_TransformBoned();
		PixelShader  = compile ps_2_0 PS_Textured();
    }
}

technique unboned
{
    pass p0 
    {		
		VertexShader = compile vs_2_0 VS_TransformUnboned();
		PixelShader  = compile ps_2_0 PS_Textured();
    }
}

technique batchedUnboned
{
    pass p0 
    {		
		VertexShader = compile vs_2_0 VS_TransformBatchedSM1();
		PixelShader  = compile ps_2_0 PS_Textured();
    }
}