/*********************************************************************NVMH3****

Terrain rendering.
This is a port of the old DX8 ASM shaders --
but with a normal map per layer, and support for 3 directional lights and 3 points.
-specular mask per layer
-height map per layer for parallax mapping

******************************************************************************/

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

#include "..\mrt.fx"

struct DirectionalLight
{
    float3 Direction    : DIRECTION;
    float3 Diffuse      : DIFFUSE;
    float3 Specular     : SPECULAR;
};

struct PointLight
{
    float4 Position_Att0     : POSITION_ATT0;
    float4 Diffuse_Att1      : DIFFUSE_ATT1;
    float4 Specular_Att2     : SPECULAR_ATT2;
};

struct Material
{
    float4 Diffuse_Opacity  : DIFFUSE_OPACITY;
    float4 Specular_Power : SPECULAR_POWER;
    float3 Ambient  : AMBIENT;
    float3 Emissive : EMISSIVE;
};

DirectionalLight    dirLights[3]    : DIRLIGHT;
PointLight          pointLights[3]  : POINTLIGHT;
Material            matSettings   : MATERIAL;

float4 DiffuseOpacity0 : DIFFUSE_OPACITY0;
float4 DiffuseOpacity1 : DIFFUSE_OPACITY1;
float4 DiffuseOpacity2 : DIFFUSE_OPACITY2;
float4 DiffuseOpacity3 : DIFFUSE_OPACITY3;

float4 Specular_Power0 : SPECULAR_POWER0;
float4 Specular_Power1 : SPECULAR_POWER1;
float4 Specular_Power2 : SPECULAR_POWER2;
float4 Specular_Power3 : SPECULAR_POWER3;

float3 Surface_Ambient0 : SURFACE_AMBIENT0;
float3 Surface_Ambient1 : SURFACE_AMBIENT1;
float3 Surface_Ambient2 : SURFACE_AMBIENT2;
float3 Surface_Ambient3 : SURFACE_AMBIENT3;

float3 ambientLevel : AMBIENT = {0.3, 0.3, 0.3};
float3 campos : CAMERAPOS;

float4x4 UVTransform0 : UVTransform4x4;
float4x4 UVTransform1 : UVTransform4x4;
float4x4 UVTransform2 : UVTransform4x4;
float4x4 UVTransform3 : UVTransform4x4;


// Parallax mapping constants
float HeightScale0 : HEIGHTSCALE0 = 0.0;
float HeightScale1 : HEIGHTSCALE1 = 0.0;
float HeightScale2 : HEIGHTSCALE2 = 0.0;
float HeightScale3 : HEIGHTSCALE3 = 0.0;

float HeightBias0 : HEIGHTBIAS0 = 0.0;
float HeightBias1 : HEIGHTBIAS1 = 0.0;
float HeightBias2 : HEIGHTBIAS2 = 0.0;
float HeightBias3 : HEIGHTBIAS3 = 0.0;



float4x4 LightViewProj0 : LightViewProj0;

texture ShadowMap0 : ShadowMap0;
sampler ShadowMapTextureSampler0 = sampler_state 
{
    texture = <ShadowMap0>;
    MinFilter = Point;
    MagFilter = Point;
    MipFilter = Point;
    AddressU = Border;
    AddressV = Border;
    //BorderColor = 0xFFFFFFFF;
    BorderColor = .0f;
};


// UV rotate bad! 
float4x4 UVRotate : UVRotate4x4;

float  timeScale : TimeScale = 0.0f;
float3 Dimensions : Dimensions;


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

texture revealTexture1 : Custom0;
sampler RevealTextureSampler1 = sampler_state 
{
    texture = <revealTexture1>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture revealTexture2 : Custom1;
sampler RevealTextureSampler2 = sampler_state 
{
    texture = <revealTexture2>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture revealTexture3 : Custom2;
sampler RevealTextureSampler3 = sampler_state 
{
    texture = <revealTexture3>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};


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

texture revealBumpTexture1 : Custom3;
sampler RevealBumpTextureSampler1 = sampler_state 
{
    texture = <revealBumpTexture1>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture revealBumpTexture2 : Custom4;
sampler RevealBumpTextureSampler2 = sampler_state 
{
    texture = <revealBumpTexture2>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture revealBumpTexture3 : Custom5;
sampler RevealBumpTextureSampler3 = sampler_state 
{
    texture = <revealBumpTexture3>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};


//---------------------------
// Specular masks
texture specMaskTexture0 : Custom6;
sampler SpecMaskTextureSampler0 = sampler_state 
{
    texture = <specMaskTexture0>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture specMaskTexture1 : Custom7;
sampler SpecMaskTextureSampler1 = sampler_state 
{
    texture = <specMaskTexture1>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture specMaskTexture2 : Custom8;
sampler SpecMaskTextureSampler2 = sampler_state 
{
    texture = <specMaskTexture2>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture specMaskTexture3 : Custom9;
sampler SpecMaskTextureSampler3 = sampler_state 
{
    texture = <specMaskTexture3>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};


//---------------------------
// Heightmaps for parallax mapping
texture heightTexture0 : Custom10;
sampler HeightTextureSampler0 = sampler_state 
{
    texture = <heightTexture0>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture heightTexture1 : Custom11;
sampler HeightTextureSampler1 = sampler_state 
{
    texture = <heightTexture1>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture heightTexture2 : Custom12;
sampler HeightTextureSampler2 = sampler_state 
{
    texture = <heightTexture2>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

texture heightTexture3 : Custom13;
sampler HeightTextureSampler3 = sampler_state 
{
    texture = <heightTexture3>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};


// Lightmap
texture LightmapTexture : LightmapTexture;
sampler LightmapTextureSampler = sampler_state 
{
    texture = <LightmapTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};



//------------------------------------
struct vertexInput {
    float4 position             : POSITION;
    float4 blendgoo             : COLOR0;
    float3 normal               : NORMAL;
    float4 tangentVec           : TANGENT;
    float2 noisefactor          : COLOR1;
};    

struct vertexOutput
{
    float4 hPosition : POSITION;
    float4 blendgoo         : COLOR0;
    float2 texCoordDiffuse0   : TEXCOORD0;
    float2 texCoordDiffuse1   : TEXCOORD1;
    float2 texCoordDiffuse2   : TEXCOORD2;
    float2 texCoordDiffuse3   : TEXCOORD3;
    float3 posWorld         : TEXCOORD4;
    float3 lightVec         : TEXCOORD5;
    float3 lightVec2        : TEXCOORD6;
    //float3 lightVec3        : TEXCOORD3;
    float3 viewVec          : TEXCOORD7;
    float3 pointLight       : TEXCOORD8;
    //float3 pointLight2      : TEXCOORD6;
    //float3 pointLight3      : TEXCOORD7;
};


struct vertexOutputExtents
{
    float4 hPosition : POSITION;
    float4 blendgoo         : COLOR0;
    float2 texCoordDiffuse0   : TEXCOORD0;
    float2 texCoordDiffuse1   : TEXCOORD1;
    float2 texCoordDiffuse2   : TEXCOORD2;
    float2 texCoordDiffuse3   : TEXCOORD3;
    float3 posWorld         : TEXCOORD4;
    float3 lightVec         : TEXCOORD5;
    float3 lightVec2        : TEXCOORD6;
    //float3 lightVec3        : TEXCOORD3;
    float4 posShadowMap       : TEXCOORD7;
    float3 pointLight       : TEXCOORD8;
    //float3 pointLight2      : TEXCOORD6;
    //float3 pointLight3      : TEXCOORD7;
};


float WorkingSaturate(float x)
{
    if (x<0)
        x = 0;
    else if (x>1)
        x = 1;
    return x;
}

//------------------------------------
vertexOutput VS_TransformAndTexture(vertexInput IN) 
{
    vertexOutput OUT;
    
    float4 newPos = IN.position;
    //newPos.y += sin(timeScale) * 7.0f * IN.noisefactor.x;
    
    OUT.hPosition = mul( newPos, worldViewProj);
        
    OUT.blendgoo = IN.blendgoo;
  
    float4 newTangent = IN.tangentVec; //= mul( IN.tangentVec, UVRotate );
    
  //  float3x3 worldToTangentSpace;
//    worldToTangentSpace[0] = normalize( mul( newTangent.xyz, world ) );
    //worldToTangentSpace[1] = normalize( mul( cross(newTangent.xyz, IN.normal), world)*newTangent.w );   
    //worldToTangentSpace[2] = normalize( mul( IN.normal, world ) );

 	float3x3 worldToTangentSpace;
    worldToTangentSpace[0] = mul( newTangent.xyz, world );
    worldToTangentSpace[1] = mul( cross(newTangent.xyz, IN.normal), world) /* *newTangent.w */;   
    worldToTangentSpace[2] = mul( IN.normal, world );
  
   
    OUT.posWorld = mul(newPos, world);

    //// -direction
    OUT.lightVec = mul( worldToTangentSpace, -dirLights[0].Direction );
    OUT.lightVec2 = mul( worldToTangentSpace, -dirLights[1].Direction );
    //OUT.lightVec3 = mul( worldToTangentSpace, -dirLights[2].Direction );

    OUT.viewVec = mul( worldToTangentSpace, campos - OUT.posWorld );
    
    //// point light: -direction
    float3 pLightDir = pointLights[0].Position_Att0.xyz - OUT.posWorld.xyz;
    OUT.pointLight.xyz = ( mul( worldToTangentSpace, (pLightDir) ) );
    //
    //float3 pLightDir2 = pointLights[1].Position_Att0.xyz - OUT.posWorld.xyz;
    //OUT.pointLight2.xyz = ( mul( worldToTangentSpace, (pLightDir2) ) );

    //float3 pLightDir3 = pointLights[2].Position_Att0.xyz - OUT.posWorld.xyz;
   // OUT.pointLight3.xyz = ( mul( worldToTangentSpace, (pLightDir3) ) );
        
    float u = OUT.posWorld.x;
    float v = OUT.posWorld.z;

    float4 baseUVs = float4(u,0,v,1);   
    //    float3 viewDir = normalize( IN.viewVec );
    // viewDir.y = -viewDir.y;
    
  
    float4 uvs = mul( baseUVs, UVTransform0 );     
    OUT.texCoordDiffuse0.x = uvs.x;
    OUT.texCoordDiffuse0.y = uvs.z;

    uvs = mul( baseUVs, UVTransform1 );
    OUT.texCoordDiffuse1.x = uvs.x;
    OUT.texCoordDiffuse1.y = uvs.z;

    uvs = mul( baseUVs, UVTransform2 );
    OUT.texCoordDiffuse2.x = uvs.x;
    OUT.texCoordDiffuse2.y = uvs.z;

    uvs = mul( baseUVs, UVTransform3 );
    OUT.texCoordDiffuse3.x = uvs.x;
    OUT.texCoordDiffuse3.y = uvs.z;
    return OUT;
}

//// Calculates diffuse and specular lighting for a point light, including light colors
void PS_PointLightDS(PointLight pointL, float3 lightToPixelT, float3 surfaceNormal, float3 posWorld, out float3 pointDiffuse, float power, float3 eyeVecT, out float3 pointSpec)
{
  float3 lightToPixelW = pointL.Position_Att0.xyz - posWorld;  
  float distSquared = dot( lightToPixelW, lightToPixelW );
  float dist = sqrt( distSquared );
  // attenuation
  // att = 1 / (a0 + a1*d + a2*d*d)
  float atten = 1 / (pointL.Position_Att0.w + pointL.Diffuse_Att1.w*dist + pointL.Specular_Att2.w*distSquared );     
  float3 pointLightDir = normalize( lightToPixelT );
  float LdN = dot(surfaceNormal, pointLightDir);
  
  float3 halfVec = normalize(pointLightDir + eyeVecT);
  float ndH = dot(halfVec, surfaceNormal);
    
  float4 vLit = saturate(lit(LdN, ndH, power));
  pointDiffuse = vLit.y*atten*pointL.Diffuse_Att1.xyz;   
  pointSpec = vLit.z *atten*pointL.Specular_Att2.xyz;
}

//// Calculates diffuse and specular lighting for a point light, including light colors
void PS_PointLightD(PointLight pointL, float3 lightToPixelT, float3 surfaceNormal, float3 posWorld, out float3 pointDiffuse )
{
  float3 lightToPixelW = pointL.Position_Att0.xyz - posWorld;  
  float distSquared = dot( lightToPixelW, lightToPixelW );
  float dist = sqrt( distSquared );
  // attenuation
  // att = 1 / (a0 + a1*d + a2*d*d)
  float atten = 1 / (pointL.Position_Att0.w + pointL.Diffuse_Att1.w*dist + pointL.Specular_Att2.w*distSquared );     
  float3 pointLightDir = normalize( lightToPixelT );
  float LdN = dot(surfaceNormal, pointLightDir);
  
 // float3 halfVec = normalize(pointLightDir + eyeVecT);
 // float ndH = dot(halfVec, surfaceNormal);
    
  //float4 vLit = lit(LdN, ndH, power);
  pointDiffuse = LdN*atten*pointL.Diffuse_Att1.xyz;   
  
}



//// Calculates diffuse and specular lighting for a directional light, including the light colors
void PS_DirLightDS(DirectionalLight dirLight, float3 dirLightDirT, float3 pixelNormalT, out float3 diffuse, float power, float3 eyeVecT, out float3 specular)
{
    float LdN = dot(-dirLightDirT, pixelNormalT);
    float3 halfVec = normalize((-dirLightDirT + eyeVecT));
    float ndH = dot(halfVec, pixelNormalT);
    float4 vLit = saturate(lit(LdN, ndH, power));
    diffuse = dirLight.Diffuse * vLit.y;
    specular = vLit.z * dirLight.Specular;
}

//// Calculates diffuse and specular lighting for a directional light, including the light colors
void PS_DirLightD(DirectionalLight dirLight, float3 dirLightDirT, float3 pixelNormalT, out float3 diffuse )
{
    float LdN = saturate( dot(-dirLightDirT, pixelNormalT) );
    diffuse = dirLight.Diffuse * LdN;
}



//-----------------------------------
PS_OUTPUT PS_Textured( vertexOutput IN)
{       
  

  // Lightmap
    float2 lmUVs = IN.posWorld.xz / Dimensions.xz;
    lmUVs = IN.posWorld.xz / Dimensions.xz;
    float4 lightMap = tex2D( LightmapTextureSampler, lmUVs );

    // Parallax mapping: offset uvs based on height
    //float4 height0 = tex2D( HeightTextureSampler0, texCoordDiffuse0 );
    //float4 height1 = tex2D( HeightTextureSampler1, texCoordDiffuse1 );
    //float4 height2 = tex2D( HeightTextureSampler2, texCoordDiffuse2 );
    
    // Parallax mapping disabled
    //float4 height3 = tex2D( HeightTextureSampler3, texCoordDiffuse3 );
    //height0.x = HeightScale0 * height0.x + HeightBias0;
    //height1.x = HeightScale1 * height1.x + HeightBias1;
    //height2.x = HeightScale2 * height2.x + HeightBias2;
    //height3.x = HeightScale3 * height3.x + HeightBias3;

    //texCoordDiffuse0 = (height0.x * viewDir) + texCoordDiffuse0;
    //texCoordDiffuse1 = (height1.x * viewDir) + texCoordDiffuse1;
    //texCoordDiffuse2 = (height2.x * viewDir) + texCoordDiffuse2;
    //texCoordDiffuse3 = (height3.x * viewDir) + texCoordDiffuse3;

    float4 diffuseTexture = tex2D( RevealTextureSampler0, IN.texCoordDiffuse0 );
    float4 revealTexture0 = tex2D( RevealTextureSampler1, IN.texCoordDiffuse1 );
    float4 revealTexture1 = tex2D( RevealTextureSampler2, IN.texCoordDiffuse2 );
    float4 revealTexture2 = tex2D( RevealTextureSampler3, IN.texCoordDiffuse3 );

    float3 normalTexture = (2 * (tex2D( RevealBumpTextureSampler0, IN.texCoordDiffuse0 ))) - 1;
    float3 revealNormalTexture0 = (2 * (tex2D( RevealBumpTextureSampler1, IN.texCoordDiffuse1 ))) - 1;
    float3 revealNormalTexture1 = (2 * (tex2D( RevealBumpTextureSampler2, IN.texCoordDiffuse2 ))) - 1;
    float3 revealNormalTexture2 = (2 * (tex2D( RevealBumpTextureSampler3, IN.texCoordDiffuse3 ))) - 1;

    //// Specular masks
    //float4 specMask0 = tex2D( SpecMaskTextureSampler0, texCoordDiffuse0 );
    //float4 specMask1 = tex2D( SpecMaskTextureSampler1, texCoordDiffuse1 );
    //float4 specMask2 = tex2D( SpecMaskTextureSampler2, texCoordDiffuse2 );
    //float4 specMask3 = tex2D( SpecMaskTextureSampler3, texCoordDiffuse3 );
       
    float4 mixedDiffuse = lerp( diffuseTexture, revealTexture0, IN.blendgoo.x );
    mixedDiffuse = lerp( mixedDiffuse, revealTexture1, IN.blendgoo.y );
    mixedDiffuse = lerp( mixedDiffuse, revealTexture2, IN.blendgoo.z );
  
    float3 mixedNormal = lerp( normalTexture, revealNormalTexture0, IN.blendgoo.x );
    mixedNormal = lerp( mixedNormal, revealNormalTexture1, IN.blendgoo.y );
    mixedNormal = lerp( mixedNormal, revealNormalTexture2, IN.blendgoo.z );
    mixedNormal = normalize(mixedNormal);

    //float3 mixedSpecularMask = lerp( specMask0, specMask1, IN.blendgoo.x );
    //mixedSpecularMask = lerp( mixedSpecularMask, specMask2, IN.blendgoo.y );
    //mixedSpecularMask = lerp( mixedSpecularMask, specMask3, IN.blendgoo.z );
    
    //float  mixedSpecPower = lerp( Specular_Power0.w, Specular_Power1.w, IN.blendgoo.x );
    //mixedSpecPower = lerp( mixedSpecPower, Specular_Power2.w, IN.blendgoo.y );
    //mixedSpecPower = lerp( mixedSpecPower, Specular_Power3.w, IN.blendgoo.z );


    //float3 mixedSpecColor = lerp( Specular_Power0.xyz, Specular_Power1.xyz, IN.blendgoo.x );
    //mixedSpecColor = lerp( mixedSpecColor, Specular_Power2.xyz, IN.blendgoo.y );
    //mixedSpecColor = lerp( mixedSpecColor, Specular_Power3.xyz, IN.blendgoo.z );

    //float4 mixedMatDiffuse = lerp( DiffuseOpacity0, DiffuseOpacity1, IN.blendgoo.x );
    //mixedMatDiffuse = lerp( mixedMatDiffuse, DiffuseOpacity2, IN.blendgoo.y );
    //mixedMatDiffuse = lerp( mixedMatDiffuse, DiffuseOpacity3, IN.blendgoo.z );

    //float3 mixedMatAmbient = lerp( Surface_Ambient0, Surface_Ambient1, IN.blendgoo.x );
    //mixedMatAmbient = lerp( mixedMatAmbient, Surface_Ambient2, IN.blendgoo.y );
    //mixedMatAmbient = lerp( mixedMatAmbient, Surface_Ambient3, IN.blendgoo.z );

    float3 lightDir = normalize( IN.lightVec );
    float3 lightDir2 = normalize( IN.lightVec2 );
    //float3 lightDir3 = normalize( IN.lightVec3 );

    float3 dirDiffuse;
    float3 dirSpec;
    //PS_DirLightDS( dirLights[0], -lightDir, mixedNormal, dirDiffuse, mixedSpecPower, viewDir, dirSpec );
    PS_DirLightD( dirLights[0], -lightDir, mixedNormal, dirDiffuse );

	// Apply lightmap
	dirDiffuse.xyz *= lightMap;
	//dirSpec.xyz *= lightMap;

    float3 dirDiffuse2;
    float3 dirSpec2;
    //PS_DirLightDS( dirLights[1], -lightDir2, mixedNormal, dirDiffuse2, mixedSpecPower, viewDir, dirSpec2 );
    PS_DirLightD( dirLights[1], -lightDir2, mixedNormal, dirDiffuse2 );


//    3rd directional light disabled    
//    float3 dirDiffuse3;
//    float3 dirSpec3;
//    PS_DirLightDS( dirLights[2], -lightDir3, mixedNormal, dirDiffuse3, mixedSpecPower, viewDir, dirSpec3 );

    //// 1st point light
    float3 pointDiffuse;
    float3 pointSpec;
    //PS_PointLightDS(pointLights[0], IN.pointLight.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse, mixedSpecPower, viewDir, pointSpec);
    PS_PointLightD(pointLights[0], IN.pointLight.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse );

    //// 2nd point light: 
//    float3 pointDiffuse2;
//    float3 pointSpec2;
//    PS_PointLightDS(pointLights[1], IN.pointLight2.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse2, mixedSpecPower, viewDir, //pointSpec2);

    // 3rd point light: 
//    float3 pointDiffuse3;
//    float3 pointSpec3;
//    PS_PointLightDS(pointLights[2], IN.pointLight3.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse3, mixedSpecPower, viewDir, //pointSpec3);

    float3 pointLightSum;
    pointLightSum = pointDiffuse;
//    pointLightSum += pointDiffuse2;
//    pointLightSum += pointDiffuse3;

    float3 directionalSum;
    directionalSum = dirDiffuse*dirLights[0].Diffuse;
    directionalSum += dirDiffuse2*dirLights[1].Diffuse;
//    directionalSum += dirDiffuse3*dirLights[2].Diffuse;

    float3 specularSum;
//    specularSum = (pointSpec + pointSpec2 + pointSpec3);
//    specularSum += (dirSpec + dirSpec2 + dirSpec3); 
    //specularSum = dirSpec + dirSpec2 + pointSpec;



	float4 outColor = float4( 0, 0, 0, 1 );
    //float4 outColor = mixedDiffuse;
    //outColor.xyz = mixedMatAmbient * ambientLevel;
    outColor.xyz += directionalSum + pointLightSum;
    outColor.xyz *= mixedDiffuse; //  * mixedMatDiffuse;    
    //outColor.xyz += (specularSum * mixedSpecColor * mixedSpecularMask);
    outColor.w = 1.0f;
    
   // outColor.xyz = directionalSum;
    
    PS_OUTPUT Out;
    SetPSOutput( Out, outColor, float4( campos - IN.posWorld.xyz, 1) );
    return Out;
}






//------------------------------------
vertexOutputExtents VS_TransformAndTextureExtents(vertexInput IN) 
{
    vertexOutputExtents OUT;
    
    float4 newPos = IN.position;
    //newPos.y += sin(timeScale) * 7.0f * IN.noisefactor.x;
    
    OUT.hPosition = mul( newPos, worldViewProj);
        
    OUT.blendgoo = IN.blendgoo;
  
    float4 newTangent = IN.tangentVec; //= mul( IN.tangentVec, UVRotate );
    
    float3x3 worldToTangentSpace;
    worldToTangentSpace[0] = normalize( mul( newTangent.xyz, world ) );
    worldToTangentSpace[1] = normalize( mul( cross(newTangent.xyz, IN.normal), world)*newTangent.w );   
    worldToTangentSpace[2] = normalize( mul( IN.normal, world ) );

   	float4 posWorld = mul(newPos, world);
    OUT.posWorld = posWorld; 

    //// -direction
    OUT.lightVec = mul( worldToTangentSpace, -dirLights[0].Direction );
    OUT.lightVec2 = mul( worldToTangentSpace, -dirLights[1].Direction );
      
    //// point light: -direction
    float3 pLightDir = pointLights[0].Position_Att0.xyz - OUT.posWorld.xyz;
    OUT.pointLight.xyz = ( mul( worldToTangentSpace, (pLightDir) ) );
           
    float u = OUT.posWorld.x;
    float v = OUT.posWorld.z;

    float4 baseUVs = float4(u,0,v,1);        
  
    float4 uvs = mul( baseUVs, UVTransform0 );     
    OUT.texCoordDiffuse0.x = uvs.x;
    OUT.texCoordDiffuse0.y = uvs.z;

    uvs = mul( baseUVs, UVTransform1 );
    OUT.texCoordDiffuse1.x = uvs.x;
    OUT.texCoordDiffuse1.y = uvs.z;

    uvs = mul( baseUVs, UVTransform2 );
    OUT.texCoordDiffuse2.x = uvs.x;
    OUT.texCoordDiffuse2.y = uvs.z;

    uvs = mul( baseUVs, UVTransform3 );
    OUT.texCoordDiffuse3.x = uvs.x;
    OUT.texCoordDiffuse3.y = uvs.z;
    
    OUT.posShadowMap = mul( posWorld, LightViewProj0 );
    
    return OUT;
}

//-----------------------------------
PS_OUTPUT PS_TexturedExtents( vertexOutputExtents IN)
{       
  
  // Lightmap
    float2 lmUVs = IN.posWorld.xz / Dimensions.xz;
    lmUVs = IN.posWorld.xz / Dimensions.xz;
    float4 lightMap = tex2D( LightmapTextureSampler, lmUVs );

    float4 diffuseTexture = tex2D( RevealTextureSampler0, IN.texCoordDiffuse0 );
    float4 revealTexture0 = tex2D( RevealTextureSampler1, IN.texCoordDiffuse1 );
    float4 revealTexture1 = tex2D( RevealTextureSampler2, IN.texCoordDiffuse2 );
    float4 revealTexture2 = tex2D( RevealTextureSampler3, IN.texCoordDiffuse3 );

    float3 normalTexture = (2 * (tex2D( RevealBumpTextureSampler0, IN.texCoordDiffuse0 ))) - 1;
    float3 revealNormalTexture0 = (2 * (tex2D( RevealBumpTextureSampler1, IN.texCoordDiffuse1 ))) - 1;
    float3 revealNormalTexture1 = (2 * (tex2D( RevealBumpTextureSampler2, IN.texCoordDiffuse2 ))) - 1;
    float3 revealNormalTexture2 = (2 * (tex2D( RevealBumpTextureSampler3, IN.texCoordDiffuse3 ))) - 1;

     
    float4 mixedDiffuse = lerp( diffuseTexture, revealTexture0, IN.blendgoo.x );
    mixedDiffuse = lerp( mixedDiffuse, revealTexture1, IN.blendgoo.y );
    mixedDiffuse = lerp( mixedDiffuse, revealTexture2, IN.blendgoo.z );
  
    float3 mixedNormal = lerp( normalTexture, revealNormalTexture0, IN.blendgoo.x );
    mixedNormal = lerp( mixedNormal, revealNormalTexture1, IN.blendgoo.y );
    mixedNormal = lerp( mixedNormal, revealNormalTexture2, IN.blendgoo.z );
    mixedNormal = normalize(mixedNormal);

    float3 lightDir = normalize( IN.lightVec );
    float3 lightDir2 = normalize( IN.lightVec2 );
  
    float3 dirDiffuse;
    float3 dirSpec;
    //PS_DirLightDS( dirLights[0], -lightDir, mixedNormal, dirDiffuse, mixedSpecPower, viewDir, dirSpec );
    PS_DirLightD( dirLights[0], -lightDir, mixedNormal, dirDiffuse );

	// Apply lightmap
	dirDiffuse.xyz *= lightMap;

    float3 dirDiffuse2;
    float3 dirSpec2;
    //PS_DirLightDS( dirLights[1], -lightDir2, mixedNormal, dirDiffuse2, mixedSpecPower, viewDir, dirSpec2 );
    PS_DirLightD( dirLights[1], -lightDir2, mixedNormal, dirDiffuse2 );

    //// 1st point light
    float3 pointDiffuse;
    float3 pointSpec;
    //PS_PointLightDS(pointLights[0], IN.pointLight.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse, mixedSpecPower, viewDir, pointSpec);
    PS_PointLightD(pointLights[0], IN.pointLight.xyz, mixedNormal.xyz, IN.posWorld, pointDiffuse );

    float3 pointLightSum;
    pointLightSum = pointDiffuse;

    float3 directionalSum;
    directionalSum = dirDiffuse*dirLights[0].Diffuse;
    directionalSum += dirDiffuse2*dirLights[1].Diffuse;


	float4 outColor = float4( 0, 0, 0, 1 );
    //float4 outColor = mixedDiffuse;
    //outColor.xyz = mixedMatAmbient * ambientLevel;
    outColor.xyz += directionalSum + pointLightSum;
    outColor.xyz *= mixedDiffuse; //  * mixedMatDiffuse;    
    //outColor.xyz += (specularSum * mixedSpecColor * mixedSpecularMask);
    outColor.w = 1.0f;
    
    
    float4 shadowdepth = tex2Dproj(ShadowMapTextureSampler0, IN.posShadowMap);   
    float4 posShadowMap = IN.posShadowMap;
    float fDepth = (posShadowMap.z / posShadowMap.w) - 0.00001;
    float islit = (shadowdepth.r >= fDepth ); 

	if( shadowdepth.x == 0.0f )
		islit = 0.0f;
		
	outColor = lerp( outColor*0.2f, outColor, islit );
    
    //outColor = float4( 1.0f, islit, islit, 1);
    
    PS_OUTPUT Out;
    SetPSOutput( Out, outColor, float4( campos - IN.posWorld.xyz, 1) );
    return Out;
}



//-----------------------------------
technique textured
{
    pass p0 
    {       

        VertexShader = compile vs_3_0 VS_TransformAndTexture();
        PixelShader  = compile ps_3_0 PS_Textured();
    }
}


technique shadowExtents
{
    pass p0 
    {       

        VertexShader = compile vs_3_0 VS_TransformAndTextureExtents();
        PixelShader  = compile ps_3_0 PS_TexturedExtents();
    }
}
