the cutting room mirror

Embedded Source Code

This article has a talk page!This article has a talk page!
view on tcrf.net

This is a sub-page of Ghostbusters: Sanctum of Slime.

The following source code was found embedded inside the main Sanctum of Slime executable, from 0x4CD0B0 to 0x4F6365, in the PC (Steam) version of the game. This source code is not in the PS3 or Xbox 360 versions.

This needs some investigation.
Discuss ideas and findings on the talk page.
Specifically: Verify that it exists in non-Steam versions.

// Translate composite pixel options
//////////////////////////////////////
// MATRIX MULTIPLICATION
//////////////////////////////////////
float3 Transform(float3x3 mat, float3 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif
}

float4 Transform(float4x4 mat, float4 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

float2 Transform(float2x2 mat, float2 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

//this conversion will not deal with renormalizations because is a bad way to handle bad data passing to the shader.
//the main problem is that cg-compiler isn't as smart as hlsl-compiler dealing with already normalized vectors
float3x3 GetWorldToTangentMatrix(float3x3 worldmtx,float3 tangent, float3 normal)
{
    float3x3 worldToTangent = 0;
    worldToTangent[0] = normalize(Transform(worldmtx, tangent));
    worldToTangent[2] = normalize(Transform(worldmtx, normal));
    worldToTangent[1] = normalize(cross(worldToTangent[0], worldToTangent[2]));    

    return worldToTangent;
}

float4 TransformPlanarReflection(float4 inPos)
{
    float4x4    matTexScale = 0;

#if !defined(_GCM)
    matTexScale._m00 = 0.5f;
    matTexScale._m11 =  -.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m03 = 0.5f; 
    matTexScale._m13 = 0.5f;
    matTexScale._m23 = 1.0f; 
    matTexScale._m33 = 1.0f;
#else
    matTexScale._m00 = 0.5f;
    matTexScale._m11 = -0.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m30 = 0.5f; 
    matTexScale._m31 = 0.5f;
    matTexScale._m32 = 1.0f; 
    matTexScale._m33 = 1.0f;
#endif

    return Transform(matTexScale,inPos);
}

 
#define _COMPOSITE_CGFX

// In the case low, med or high shadows are used, we are using shadows!
#if defined (_SHADOW_LOW) || defined (_SHADOW_MED) || defined(_SHADOW_HI)
    #define __USE_SHADOWMAP
#endif

#ifndef _POINTSPRITE

#ifdef _PIXELOPTION0
    #define _COMPOSITE_LIGHTED
#endif

#ifdef _PIXELOPTION1
    #define _COMPOSITE_2LAYERS
#endif
    
#ifdef _PIXELOPTION2
    #define _COMPOSITE_L0_ADD
#endif
    
#ifdef _PIXELOPTION3
    #define _COMPOSITE_L0_MULTIPLY
#endif



// For comodity we define _COMPOSITE_2LAYERS if there is a layer1 operation
#if defined(_COMPOSITE_L1_ADD) || defined(_COMPOSITE_L1_MULTIPLY) || defined(_COMPOSITE_L1_MULTIPLY2X) || defined(_COMPOSITE_L1_REPLACE) || defined(_UV1_USESCHANNEL0) || defined(_UV1_USESCHANNEL1)
    #define _COMPOSITE_2LAYERS
#endif

//////////////////////////////////////
// SKINNING
//////////////////////////////////////

#if defined(_VERTEX_SHADER) && defined(_USE_SKINMATRIX)
uniform float4x4    g_skinMatrix[_MAXBONES];        ///< 128 Registers for skin bones

struct SKINVERTEX
{
    float4 P;
    float3 N;
    float3 T;
};

SKINVERTEX SkinVertex(float3 p, float3 n, float3 t, float4 indices, float4 weights)
{
    SKINVERTEX Out = (SKINVERTEX) 0;
    for(int i = 0; i < 4; i++)
    {
        Out.P.xyz += Transform(g_skinMatrix[indices.x], float4(p,1)).xyz * weights.x;
        Out.N += (float3)(Transform((float3x3) g_skinMatrix[indices.x], n) * weights.x);

        #if !defined(SH_VERSION_SH1)
        Out.T += (float3)(Transform((float3x3) g_skinMatrix[indices.x], t) * weights.x);
        #endif

        indices.xyzw = indices.yzwx;
        weights.xyzw = weights.yzwx;
    }

    Out.P.w = 1;
    Out.N = (float3)normalize(Out.N);
    
    #if !defined(SH_VERSION_SH1)
    Out.T = (float3)normalize(Out.T);
    #endif

    return Out;
}

#endif

//////////////////////////////////////
// END SKINNING
//////////////////////////////////////


float GetRimFading(float3 CamPos,float3 FragmentWorldPos,float3 Normal,float InvThreshold)
{
    float3 nCminP = normalize(CamPos.xyz-FragmentWorldPos.xyz);
    float NdotCmP = dot(Normal,nCminP);
    return saturate(NdotCmP*InvThreshold);
}

void ComputeFog(inout float4 PixelColor,float3 FogColor,float DistancePixelToCamera,float MinDistanceToFog,float MaxMinusMinDistanceToFog)
{
#if defined(_PIXEL_FOG)
    float CamMinusFogMin = (DistancePixelToCamera-MinDistanceToFog);
    float FogFactor  = 1-saturate(CamMinusFogMin/MaxMinusMinDistanceToFog);
    #if !defined(_ADDITIVE_PIXEL_FOG)
        PixelColor.rgb = lerp(FogColor, PixelColor.rgb, FogFactor);
    #elif defined(_ADDITIVE_PIXEL_FOG)
        PixelColor.rgb*=FogFactor;
        clip(MaxMinusMinDistanceToFog-CamMinusFogMin);
    #endif
#endif
}

//////////////////////////////////////
// UV GENERATION
//////////////////////////////////////
#ifdef _VERTEX_SHADER

#if defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_SPHEREVIEW)
    float3x3 g_matView;
#endif

float3 GetUVCoordinate3L0(float3 position, float3 normal, float3 viewer)
{
    #ifdef _UV0_AUTO_POSITION
        return position;
    #elif defined(_UV0_AUTO_REFLECTION)
        return (2.f * dot(viewer,normal) * normal - viewer) * .5f + .5f;
    #elif defined(_UV0_AUTO_NORMAL)
        return normal;
    #elif defined(_UV0_AUTO_SPHERE)
        return normal * .5f + .5f;
    #elif defined(_UV0_AUTO_SPHEREVIEW)
        float3 normalViewSpace = Transform(g_matView, normal);
        return float3(normalViewSpace.x, -normalViewSpace.y, 1.0f) * .5f + .5f;
    #else
        return normal;
    #endif  
}

float3 GetUVCoordinate3L1(float3 position, float3 normal, float3 viewer)
{
    #ifdef _UV1_AUTO_POSITION
        return position;
    #elif defined(_UV1_AUTO_REFLECTION)
        return (2.f * dot(viewer,normal) * normal - viewer) * .5f + .5f;
    #elif defined(_UV1_AUTO_NORMAL)
        return normal;
    #elif defined(_UV1_AUTO_SPHERE)
        return normal * .5f + .5f;
    #elif defined(_UV1_AUTO_SPHEREVIEW)
        float3 normalViewSpace = Transform(g_matView, normal);
        return float3(normalViewSpace.x, -normalViewSpace.y, 1.0f) * .5f + .5f;
    #else
        return normal;
    #endif  
}

#endif
//////////////////////////////////////
// END UV GENERATION
//////////////////////////////////////


//////////////////////////////////////
// VERTEX SHADER INPUT
//////////////////////////////////////
#ifdef _VERTEX_SHADER

struct Composite_InputVS
{
    float3 pos      : POSITION;         ///< Vertex position
    
#ifdef _USE_SKINMATRIX
    float4 weight   : BLENDWEIGHT;      ///< Weight vector used for skinning ( how much each bone affects the vertex )
    float4 indices  : BLENDINDICES;     ///< Index vector used for skinning ( the index of each bone )
#endif

#ifdef _HAS_NORMAL
    float3 normal   : NORMAL;           ///< Vertex Normal
#endif

#ifdef _HAS_TANGENT3
    float3 tangent  : TANGENT;          ///< Vertex tangent, for use to map to tangent space normal maps
#endif

#ifdef _HAS_TANGENT
    float4 tangent  : TANGENT;          ///< Vertex tangent, for use to map to tangent space normal maps
#endif

#ifdef _HAS_COLOR
    float4 color    : COLOR0;           ///< Diffuse color of the vertex
#endif
    
#ifdef _HAS_UV0
    float2 uv0      : TEXCOORD0;        ///< UV Coordinates for layer 0
#endif
#ifdef _HAS_UV1
    float2 uv1      : TEXCOORD1;        ///< UV Coordinates for layer 1
#endif
#ifdef _HAS_UV2
    float2 uv2      : TEXCOORD2;
#endif
};

#endif
//////////////////////////////////////
// END VERTEX SHADER INPUT
//////////////////////////////////////



//////////////////////////////////////
// LIGHTING
//////////////////////////////////////

//////////////////////////////////////
// LIGHTING INFO
#ifdef _COMPOSITE_LIGHTED

float4      g_lightDirection0;
float4      g_lightPosition0;
float4      g_lightColor0;
float4      g_lightSpecular0;

#if defined(_LIGHT1_POINT) || defined(_LIGHT1_DIRECTIONAL)
    float4      g_lightDirection1;
    float4      g_lightPosition1;
    float4      g_lightColor1;
    float4      g_lightSpecular1;
#endif

#endif //_COMPOSITE_LIGHTED

uniform float4 g_cameraPos, g_compositePixelOptions;
uniform float4 g_RimFading;

/// Tongas upload variables
float4      g_ambient;
float4      g_ambientColor;
float4      g_diffuseColor;
float4      g_emissiveColor;
float4      g_specularColor;

#define g_bloomFactor g_emissiveColor.a

///////////////////////////////////////
// FX INFO
uniform float4      g_zBlurOptions;

//////////////////////////////////////
// LIGHTING FUNCTIONS
/*
CalculateSpecularLighting
Calculates the specular lighting for an interest point
*/
float3 CalculateSpecularLighting(
            in float3 lightDirection,           ///< Direction of the light MUST BE NORMALIZED!
            in float3 lightSpecularColor,       ///< Specular color
            in float3 normalVector,             ///< Normal vector of the intereset point
            in float3 viewVector                ///< View vector of the interest point
            )
{
    float3 Half = normalize( lightDirection + viewVector);
    return lightSpecularColor.xyz * pow(saturate( dot( Half, normalVector) ), g_specularColor.a);
}

/*
CalculatePointLightAttenuation
Calculates the attenuation of a point light on a surface point
*/
float CalculatePointLightAttenuation(
     in float3  iLightDirection,            ///< Direction NOT NORMALIZED, from the point to the light position  
     float      iLightInverseRange          ///< Inverse range (1/r) of the point light  
     )
{
    float3 attenuatedLightDirection = iLightDirection * iLightInverseRange;
    return saturate ( 1.0f - dot (attenuatedLightDirection, attenuatedLightDirection));
}
     


void LightSpot_VS(float3 iDir, float invRange, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir);
    //oFactor = ( 1.0f - (oFactor  / Range) );  
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));                    
}

void LightSpot_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = iDir;
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;
    
    oD += lightColor * iD * saturate(fNDotL) * Factor;
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += Factor * lightColor * iS.xyz * pow(saturate(dot(Half,normal)), iS.a);
    #endif
}

/*
GetPointLightDirectionInTangentSpace
Retrieves the direction of a point light in tangent space
*/
float3 GetPointLightDirectionInTangentSpace( 
        float3 lightPosition,                   ///< Light position in world space
        float3 vertexPosition,                  ///< Vertex position in world space
        float3x3 worldToTangentTransform        ///< World to Tangent space transformation
        )
{
    float3 lightDir = lightPosition - vertexPosition;
    lightDir = mul(worldToTangentTransform, lightDir);
    return lightDir;
}

/*
GetPointLightDirectionInWorldSpace
Calculates the point light direction in world space
*/
float3 GetPointLightDirectionInWorldSpace(
        float3 lightPosition,                   ///< Light position in world space
        float3 vertexPosition                   //< Vertex position in world space
        )
{
    return lightPosition - vertexPosition;
}

void OutLightDirSpotPPL(float3 iDir, float invRange, float3x3 TBN, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir.xyz);
    //oFactor = ( 1.0f - (oFactor  * invRange) );   
    oDir.xyz = mul(TBN, oDir.xyz);  
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));
}

void OutLightDirSpotPVL(float3 iDir, float invRange, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir.xyz);
    //oFactor = ( 1.0f - (oFactor  / Range) );                      
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));
}

void LightDirectional_PPL_PS(float3 iDir, float3 n, float3 v, float3 iD, float3 iS, inout float3 oD, inout float3 oS)
{
    float3 fvLightDir = normalize(iDir);
    float fNDotL = dot(n, fvLightDir);      
    oD += iD * saturate(fNDotL);

    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir + v);
        oS.xyz += iS.xyz * pow(saturate(dot(Half, n)), g_specularColor.a);
    #endif
}

/*
AddPointLightContributionTangentSpace
Adds the contribution diffuse and specular lighting of a point light to a point of a surface
*/
void AddPointLightContributionTangentSpace(
    in float3       iLightDirectionTangentSpace,        ///< Direction to the light from the 3d point in tangent space
    in float3       iLightPositionWorldSpace,           ///< Position of the point light in world space
    in float        iLightInverseRange,                 ///< Inverse range of the point light (1/r)
    in float3       iLightDiffuseColor,                 ///< Diffuse color of the light
    in float3       iLightSpecularColor,                ///< Specular color of the light
    in float3       iPointNormalTangentSpace,           ///< Normal on the 3d point in tangent space
    in float3       iPointViewTangentSpace,             ///< View vector on the 3d point in tangent space
    in float3       iPointPositionWorldSpace,           ///< Position of the 3d point in world space
    inout float3    ioAcumulatedDiffuseLight,           ///< Acumulated diffuse light
    inout float3    ioAcumulatedSpecularLight           ///< Acumulated specular light
    )
{
    // Calculate attenuation of the spot light
    float lightAttenuation = CalculatePointLightAttenuation(iLightPositionWorldSpace - iPointPositionWorldSpace, iLightInverseRange );
    
    // Calculate diffuse lighting contribution
    float3 lightDirectionNormalized = normalize( iLightDirectionTangentSpace );
    float fNDotL = dot(iPointNormalTangentSpace, lightDirectionNormalized);     
    ioAcumulatedDiffuseLight += iLightDiffuseColor * saturate(fNDotL) * lightAttenuation;
    
    // Calculate specular lighting contribution
    #ifndef _MATERIAL_NOSPECULAR
        ioAcumulatedSpecularLight += lightAttenuation * 
            CalculateSpecularLighting(lightDirectionNormalized, iLightSpecularColor, iPointNormalTangentSpace, iPointViewTangentSpace );
    #endif
}

void LightPoint_PPL_PS(float3 iDir, float3 n, float3 v, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS)
{
    float3 fvLightDir = normalize(iDir);
    float fNDotL = dot(n, fvLightDir);      
    oD += iD * saturate(fNDotL) * Factor;
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+v);
        oS.rgb += Factor * iS.xyz * pow(saturate( dot(Half,n) ), g_specularColor.a);
    #endif
}

void LightSpot_PPL_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = normalize(iDir);        
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;            
    oD += saturate( lightColor * iD * saturate(fNDotL) * Factor );
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += saturate( lightColor * Factor * iS.xyz * pow(saturate(dot(Half,normal)), g_specularColor.a) );
    #endif
}
    
void LightDirectional_PVL_PS(float3 iDir, float3 normal, float3 view, float3 iD, float  transColor, float3 iS, inout float3 oD, inout float3 oS)
{
    
    float fNDotL = dot(normal, iDir);       
    oD += iD.rgb * saturate(fNDotL);
    
    #ifdef _TRANSLUCENCY
            float fNDotL2 = dot(-normal, iDir);     
            oD += iD.rgb * saturate(fNDotL2) * transColor;
    #endif
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(iDir + view);   
        oS += iS.xyz * pow( saturate(dot(Half,normal)), g_specularColor.a);
    #endif
}

/*
AddPointLightContributionWorldSpace
Adds the contribution diffuse and specular lighting of a point light to a point of a surface
*/
void AddPointLightContributionWorldSpace(
    in float3       iLightPosition,             ///< Light position in world space
    in float        iLightInverseRange,         ///< Inverse range of the point light (1/r)
    in float3       iLightDiffuseColor,         ///< Diffuse color of the light
    in float3       iLightSpecularColor,        ///< Specular color of the light
    in float3       iPointNormal,               ///< Normal of the 3d point in world space
    in float3       iPointView,                 ///< View vector of the 3d point in world space
    in float3       iPointPosition,             ///< Poisition of the 3d point in worls space
    inout float3    ioAcumulatedDiffuseLight,   ///< Acumulated diffuse lighting
    inout float3    ioAcumulatedSpecularLight   ///< Acumulated specular lighting
    )
{
    // Determiate the light direction, used for attenuation and light contribution
    float3 lightDirection = iLightPosition - iPointPosition;

    // Calculate attenuation of the spot light
    float lightAttenuation = CalculatePointLightAttenuation(lightDirection, iLightInverseRange);
    
    // Calculate diffuse lighting contribution
    lightDirection = normalize( lightDirection );
    float fNDotL = dot(iPointNormal, lightDirection);       
    ioAcumulatedDiffuseLight += iLightDiffuseColor * saturate(fNDotL) * lightAttenuation;
    
    // Calculate specular lighting contribution
    #ifndef _MATERIAL_NOSPECULAR
        ioAcumulatedSpecularLight += lightAttenuation * 
            CalculateSpecularLighting(lightDirection, iLightSpecularColor, iPointNormal, iPointView);
    #endif
}

void LightSpot_PVL_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = iDir;
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;            
    oD += lightColor * iD * saturate(fNDotL) * Factor;      
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += lightColor * Factor * iS.xyz * pow(saturate(dot(Half,normal)), g_specularColor.a);
    #endif
}


//////////////////////////////////////
// END LIGHTING
//////////////////////////////////////


//////////////////////////////////////
// VERTEX SHADER OUTPUT
//////////////////////////////////////
struct Composite_OutputVS
{
    float4 hpos         : POSITION;     ///< Clip space transformed vertex position
    float4 color        : COLOR0;       ///< Vertex color

    float3 uv0          : TEXCOORD0;    ///< UV Coordinates used by layer 1
    float3 uv1          : TEXCOORD1;    ///< UV Coordinates used by layer 2

    float4 vpos         : TEXCOORD2;    ///< Position of the vertex in world space, and shadowprojection distance

    float4 lightfactors : COLOR1;       ///< Light factos used for point lights
    float3  normal      : TEXCOORD3;    ///< Vertex normal
    float3  view            : TEXCOORD4;    ///< View direction to the vertex

    float4 lightDir0    : TEXCOORD5;    ///< Direction of light 0

#ifdef _LIGHT0_SPOT
    float4 spotProjection1  : TEXCOORD6;    ///< spot projection
#endif

#if defined(__USE_SHADOWMAP) && (defined(_LIGHT0_DIRECTIONAL) || defined(_LIGHT0_SPOT))
    float4 shadowProjection : TEXCOORD7;    ///< Shadow map projection
#endif

#ifdef _PS3_VSCLIPPLANE0
    float oClip0        : CLP0;
#endif
};
//////////////////////////////////////
// END VERTEX SHADER OUTPUT
//////////////////////////////////////


//////////////////////////////////////
// SHADOWMAPPING
//////////////////////////////////////
#ifndef _COMPOSITE_LIGHTED
    #undef __USE_SHADOWMAP
#endif

#ifdef __USE_SHADOWMAP

uniform float4x4    g_matTextureProjection;
uniform float4      g_shadowmapOptions;
uniform float4      g_texelSize89;

#define     g_ShadowmapFactor   (1-g_shadowmapOptions.x)    /// default 0.0
#define     g_ShadowmapZBias    (g_shadowmapOptions.y)      /// default -0.001

uniform sampler2D   g_shadowMap         : register(s9);
uniform samplerCUBE g_shadowCubeMap     : register(s9);

////////////////////////////////////
// DIRECTIONAL
float SampleShadowTest(float4 ShadowTexC)
{   
    #if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI
        return tex2D(g_shadowMap, ShadowTexC.xy).r >= ShadowTexC.z;     
    #else   //nVidia
        return tex2Dproj(g_shadowMap, ShadowTexC).r;
    #endif  
}

float GetShadowDirectional(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.f - ShadowTexC.y;

#ifdef _PS3
    ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _XENON
    ShadowTexC.xyz = ShadowTexC.xyz / ShadowTexC.w;
    
    // [BP] On xbox360 we are getting projected distances that are higher than 1
    // as they are not being cut by the far plane of the light frustum
    // still we need to study more this effect, even check if it can be done on vertex
    // shader stage to save gpu process
    ShadowTexC.z = min(1,ShadowTexC.z);     // Check that z the minimum value to 1
#endif
    
#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
    
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.w = 1;
            
    #if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)
        return saturate(SampleShadowTest(ShadowTexC) + g_ShadowmapFactor);
    #else

        float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 2;
        float4 tY = float4(0, g_texelSize89.w, 0, 0) * 2;
        float accum = 0;
 
        #if defined(_SHADOW_MED)
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY *  .5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY *  .5);
            return saturate((accum/4.f) + g_ShadowmapFactor);
        #elif defined(_SHADOW_HI)
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  1);  
            return saturate((accum/9.f) + g_ShadowmapFactor);
        #else
            return 1;
        #endif
    #endif  
}

/////////////////////////////////
// SPOT
//[VC]: why this is just a copy paste from spotdirectional???
float GetShadowSpotSample(float4 ShadowTexC)
{
    float shadow;

#if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI

    float a = tex2D(g_shadowMap, ShadowTexC.xy).r > ShadowTexC.z;
    float b = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, 0)).r > ShadowTexC.z;
    float c = tex2D(g_shadowMap, ShadowTexC.xy + float2(0, g_texelSize89.w)).r > ShadowTexC.z;
    float d = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, g_texelSize89.w)).r > ShadowTexC.z;

#if defined(SH_VERSION_SH2)
    return a;
#endif
    
    // transform to texel space
    float2 texelpos = (1.f/g_texelSize89.zw) * ShadowTexC;
    
    // Determine the lerp amounts           
    float2 lerps = frac( texelpos );

    // lerp between the shadow values to calculate our light amount
    shadow = lerp( lerp( a, b, lerps.x ),
                   lerp( c, d, lerps.x ),
                   lerps.y );       
    return shadow;

#else   //nVidia

    shadow = tex2Dproj(g_shadowMap, ShadowTexC).r;

#endif
    
    return shadow;
}

float GetShadowSpot(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy / TexCoords.w + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.0f - ShadowTexC.y;

    //not needed for spot lights
#ifdef _PS3
    //ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
        
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.z /= ShadowTexC.w;

    ShadowTexC.w = 1;
            
#if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)

    return saturate(GetShadowSpotSample(ShadowTexC) + g_ShadowmapFactor);
    
#endif

    float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 1;
    float4 tY = float4(0, g_texelSize89.w, 0, 0) * 1;

    float accum = 0;

#if defined(_SHADOW_MED)
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY *  .5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY *  .5); 
    return saturate((accum/4.f) + g_ShadowmapFactor);
#endif
    
#if defined(_SHADOW_HI)
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  1);
    return saturate((accum/9.f) + g_ShadowmapFactor);
#endif

    return 1;
}


/////////////////////////////////
// POINT

float GetShadowPointSample(float3 Pos)
{
    float shadow = 1;

#ifdef _LIGHT0_POINT
    shadow = texCUBE(g_shadowCubeMap, Pos.xyz-g_lightPosition0.xyz).r > (length(Pos.xyz-g_lightPosition0.xyz) * g_lightPosition0.w) + g_ShadowmapZBias;
#endif

    return shadow;
}

float GetShadowPoint(float3 Pos)
{
    return saturate(GetShadowPointSample(Pos) + g_ShadowmapFactor);
}

#endif
//////////////////////////////////////
// END SHADOWMAPPING
//////////////////////////////////////

    
//////////////////////////////////////
//VERTEX SHADER
//////////////////////////////////////

//////////////////////////////////////
// VERTEX SHADER CONSTANTS
#ifdef _VERTEX_SHADER
    float4x4 g_matWorld, g_matWorldView, g_matWorldViewProjection;

    float4 g_textureTransform0;
    float4 g_textureTransform1;

    float4 g_textureTransformExt0;
    float4 g_textureTransformExt1;

    #ifdef _LIGHT0_SPOT
        float4x4 g_matTexture2;
    #endif

#ifdef _PS3_VSCLIPPLANE0
    uniform float4  g_ps3ClipPlane0;
#endif
    
#endif

//////////////////////////////////////
// VERTEX SHADER
#ifdef _VERTEX_SHADER

void main_VS( Composite_InputVS inVertex, out Composite_OutputVS outResult )
{
    outResult = (Composite_OutputVS) 0;
    
    // Init Color
    #ifdef _HAS_COLOR
        outResult.color = inVertex.color;   
    #else
        outResult.color = float4(1,1,1,1);
    #endif
    
    // Init normal
    #if defined(_COMPOSITE_LIGHTED) && defined(_HAS_NORMAL)
        float3 normal = normalize(inVertex.normal);
    #else
        float3 normal = float3(0,0,1);
    #endif
        
        
    float4 position;

    #ifdef _USE_SKINMATRIX  
        SKINVERTEX v = SkinVertex(float4(inVertex.pos, 1), normal,float3(1,0,0), inVertex.indices, inVertex.weight);

        position    = v.P;
        normal  = v.N;
    #else
        position    = float4(inVertex.pos, 1);
    #endif //_USE_SKINMATRIX

    

    /// Transform the position to clip space
    outResult.hpos  = Transform(g_matWorldViewProjection, position);
    outResult.vpos  = Transform(g_matWorld, position);
    
#ifdef _PS3_VSCLIPPLANE0
    outResult.oClip0    = dot(outResult.vpos, g_ps3ClipPlane0);
#endif
    
#ifdef _COMPOSITE_LIGHTED
    outResult.normal    = Transform((float3x3) g_matWorld, normal);         ///< Normal in world space
#endif

#ifdef _HAS_UV0 
    outResult.uv0 = float3(inVertex.uv0, 1);
    outResult.uv1 = float3(inVertex.uv0, 1);
#endif

    /// Create parameters for autogenerated coordinates
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION) || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
        float3 P        = Transform(g_matWorldView, position);                          ///< Vertex position in view space
        float3  N       = Transform((float3x3) g_matWorld, normal);         ///< Normal in world space
        float3 V        = normalize(g_cameraPos-P);                                 ///< Viewer position
    #endif
    
    /// Calculate the uv transformations for the diffuse layer
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW)
        outResult.uv0 = GetUVCoordinate3L0(P, N, V);        
    #endif
    
    /// Calculate the uv transformation for the enviromental layer
    #if defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION) || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
        outResult.uv1 = GetUVCoordinate3L1(P, N, V);
    #elif defined(_HAS_UV1)
        #if !defined(_UV1_USESCHANNEL0) && defined(_COMPOSITE_2LAYERS)
            outResult.uv1.xy = inVertex.uv1;
        #endif
    #endif
    
    /// Finally transform the uv coordinates by the texture matrix transformations
    outResult.uv0.xy = outResult.uv0.xy * g_textureTransform0.xy + outResult.uv0.yx * g_textureTransformExt0.yx + g_textureTransform0.zw;
    outResult.uv1.xy = outResult.uv1.xy * g_textureTransform1.xy + outResult.uv1.yx * g_textureTransformExt1.yx + g_textureTransform1.zw;
    
    
#ifdef _COMPOSITE_LIGHTED
    
    /// The outResult.view vector is only used to calculate specular lighting, so if there is no specular dont calculate the view
    #ifndef _MATERIAL_NOSPECULAR
        float3 pWorld   = Transform(g_matWorld, position);                  ///< Vertex position in world space
        outResult.view      = normalize(g_cameraPos - pWorld);              ///< View direction
    #endif

    
    #ifdef _LIGHT0_DIRECTIONAL      
        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, float4(position.xyz,1));
        #endif
    #endif

    #ifdef _LIGHT0_POINT
        outResult.lightfactors.x = length(g_lightPosition0.xyz - outResult.vpos);
        outResult.lightfactors.x = saturate(1.0f - (outResult.lightfactors.x  * g_lightPosition0.w));
    #endif
    
    #ifdef _LIGHT1_POINT
        outResult.lightfactors.y = length(g_lightPosition1.xyz - outResult.vpos);
        outResult.lightfactors.y = saturate(1.0f - (outResult.lightfactors.y  * g_lightPosition1.w));
    #endif

    #ifdef _LIGHT0_SPOT
        LightSpot_VS(g_lightPosition0.xyz - outResult.vpos.xyz, g_lightPosition0.w, outResult.lightDir0.xyz, outResult.lightDir0.w);

        outResult.spotProjection1 = Transform(g_matTexture2, position);
        

        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, float4(position.xyz,1));
        #endif
    #endif

#endif //_COMPOSITE_LIGHTED
}

#endif

//////////////////////////////////////
// END VERTEX SHADER
//////////////////////////////////////


//////////////////////////////////////
//PIXEL SHADERS
//////////////////////////////////////
#ifdef _PIXEL_SHADER

//////////////////////////////////////
// SAMPLERS
uniform sampler2D g_layer0  : register(s0);         ///< First texture layer
uniform sampler2D g_layer1  : register(s1);         ///< Second texture layer
uniform sampler2D g_spot1Map: register(s8);         ///< Spot light proyection texture

#if defined(_MRT3) && !defined(_MRT2)
    #define _MRT2
#endif
#if defined(_MRT2) && !defined(_MRT1)
    #define _MRT1
#endif

struct Composite_OutputPS
{
#if !defined(_MRT)
    float4 color : COLOR0;
#else
    #if defined(_MRT_RT_0_1)
        float4 color : COLOR1;
    #elif defined(_MRT_RT_0_2)
        float4 color : COLOR2;
    #elif defined(_MRT_RT_0_3)
        float4 color : COLOR3;
    #else
        float4 color : COLOR0;
    #endif
    
    #if defined(_MRT1)
    #if defined(_MRT_RT_1_0)
        float4 color1 : COLOR0;
    #elif defined(_MRT_RT_1_2)
        float4 color1 : COLOR2;
    #elif defined(_MRT_RT_1_3)
        float4 color1 : COLOR3;
    #else
        float4 color1 : COLOR1;
    #endif
    #endif
    
    #if defined(_MRT2)
    #if defined(_MRT_RT_2_0)
        float4 color2 : COLOR0;
    #elif defined(_MRT_RT_2_1)
        float4 color2 : COLOR1;
    #elif defined(_MRT_RT_2_3)
        float4 color2 : COLOR3;
    #else
        float4 color2 : COLOR2;
    #endif
    #endif
    
    #if defined(_MRT3)
    #if defined(_MRT_RT_3_0)
        float4 color3 : COLOR0;
    #elif defined(_MRT_RT_3_1)
        float4 color3 : COLOR1;
    #elif defined(_MRT_RT_3_2)
        float4 color3 : COLOR2;
    #else
        float4 color3 : COLOR3;
    #endif
    #endif
#endif
};


//////////////////////////////////////
// FOG

#ifdef _VERTICAL_FOG
    float4      g_verticalFogColor;
    float4      g_verticalFogValues;
#endif

#ifdef _PIXEL_FOG
    float4      g_pixelFogColor;
    float4      g_pixelFogOptions;
#endif

#if defined(_ALPHA_TEST)
float4      g_PixelAlphaTesting;
#endif

#if defined(_MRT)
#define _MRT_DEFAULT_COLOR      float4(0,0,0,0)
#define _MRT_BLACK_COLOR        float4(0,0,0,1)

#ifndef _PIXEL_FOG
    float4      g_pixelFogOptions;
#endif

uniform float4      g_multilayerTextureOptions;

float4 getBloomOutput(float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;

    #if !defined(_POINTSPRITE)
    float4  ret = float4(0,0,0,1);
    ret.g = g_emissiveColor.a;
    #else
    float4  ret = float4(0,1,0,1);
    #endif

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }
    
    ret*=mulFactor;

    return ret;
}

#if !defined(_POINTSPRITE)
float4 getFocusBloomOutput(float opacity,float3 pos,float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;
    if(opacity>=1)
        mulFactor = 1;

    float4  ret = float4(0,0,0,opacity);
    ret.g = g_emissiveColor.a*opacity;

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }

    ret*=mulFactor;
    return ret;
}
#endif

#if defined(_MULTILAYER_CGFX)

//default output
float4 pso_MRT_default_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    #if !defined(_POINTSPRITE)
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
    #else
    return getBloomOutput(IN.uv.xy,g_diffuseMap);
    #endif
}

float4 pso_MRT_focusBloom_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uvcoords.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

#endif

//default output
#if defined(_COMPOSITE_CGFX)
#ifndef _POINTSPRITE
float4 pso_MRT_default_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(Composite_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(Composite_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_layer0);
}

#else
float4 pso_MRT_default_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return getBloomOutput(IN.uv.xy,g_layer0);
}
#endif
#endif

#if defined(_MRT3) && !defined(_MRT2)
#define _MRT2
#endif

#if defined(_MRT2) && !defined(_MRT1)
#define _MRT1
#endif

#if defined(_MRT1) && !defined(_MRT1_OUTMETHOD)
    #define _MRT1_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT2) && !defined(_MRT2_OUTMETHOD)
    #define _MRT2_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT3) && !defined(_MRT3_OUTMETHOD)
    #define _MRT3_OUTMETHOD     pso_MRT_default_output
#endif
#endif

void Composite_MainPS(Composite_OutputVS IN,out float4 OUT);

void main_PS( Composite_OutputVS inData, out Composite_OutputPS outResult   )
{
    float4 color;
    Composite_MainPS(inData,color);

    outResult.color = color;

    #if defined(_MRT1)
        outResult.color1 = _MRT1_OUTMETHOD(inData, outResult.color);
    #endif

    #if defined(_MRT2)
        outResult.color2 = _MRT2_OUTMETHOD(inData, outResult.color);
    #endif

    #if defined(_MRT3)
        outResult.color3 = _MRT3_OUTMETHOD(inData,outResult.color);
    #endif
    
    #if defined(_ALPHA_TEST)
        clip(outResult.color.a-g_PixelAlphaTesting.x);
    #endif  
}


void Composite_MainPS( Composite_OutputVS inData, out float4 outResult)
{
    outResult = inData.color;
    outResult.a = 1;
    
#ifdef _COMPOSITE_LIGHTED
    float3 normal = normalize(inData.normal);
    
    /// Calculate lighting
    float   fNDotL      = 0;
    float3  myLight     = 0;
    float3  fvLightDir  = 0;

    float3  Half        = 0;
    float3  mySpecular  = 0;
    float3  view        = normalize(inData.view);
    
    /// Calculate directional lighting      
    #ifdef _LIGHT0_DIRECTIONAL
        fNDotL      = dot(normal, -g_lightDirection0);      
        myLight     += g_lightColor0.rgb * saturate(max(0, fNDotL));
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(-g_lightDirection0 + view);    
            mySpecular  += g_lightSpecular0 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
        

        #ifdef __USE_SHADOWMAP
            float shadow = GetShadowDirectional(inData.shadowProjection);
            myLight *= shadow;
        
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
        
    #endif
    
    #ifdef _LIGHT1_DIRECTIONAL
        fNDotL      = dot(normal, -g_lightDirection1);      
        myLight     += g_lightColor1.rgb * saturate(max(0, fNDotL));
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(-g_lightDirection1 + view);    
            mySpecular  += g_lightSpecular1.rgb * pow(max(0, dot(Half,normal)) ,g_specularColor.a);
        #endif
    #endif
    
    /// Calculate point lights
    #ifdef _LIGHT0_POINT
        fvLightDir = normalize(g_lightPosition0.xyz - inData.vpos);     
        fNDotL = dot(normal, fvLightDir);       
        myLight += g_lightColor0.rgb * saturate(max(0, fNDotL)) * inData.lightfactors.x;                
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(fvLightDir+view);
            mySpecular  += inData.lightfactors.x * g_lightSpecular0 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
        

        #ifdef __USE_SHADOWMAP
            float shadow = GetShadowPointSample(inData.vpos);
            myLight *= shadow;
        
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
        
    #endif
    
    #ifdef _LIGHT1_POINT
        fvLightDir  = normalize(g_lightPosition1.xyz - inData.vpos);        
        fNDotL      = dot(normal, fvLightDir);      
        myLight += g_lightColor1.rgb * saturate(max(0, fNDotL)) * inData.lightfactors.y;                

        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(fvLightDir+view);
            mySpecular += inData.lightfactors.y * g_lightSpecular1 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
    #endif
    
    #ifdef _LIGHT0_SPOT
        fvLightDir = g_lightPosition0.xyz - inData.vpos;
        if(dot(normalize(fvLightDir),-g_lightDirection0.xyz)>0)
            LightSpot_PS(normalize(inData.lightDir0.xyz), inData.normal, inData.view, inData.lightDir0.w, g_lightColor0.xyz, float4(g_lightSpecular0.xyz,g_specularColor.w), myLight, mySpecular, g_spot1Map, inData.spotProjection1);
        #ifdef __USE_SHADOWMAP
            float shadow = GetShadowSpot(inData.shadowProjection);
            myLight *= shadow;
        
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
        
    #endif  

    float3 ambient = 0;
    #ifndef _LIGHT0_SPOT
        ambient = g_ambient.rgb * g_ambientColor.rgb;
    #endif
    
    outResult.rgb *= myLight * g_diffuseColor.rgb + ambient;
    
#else
    // No Lighting
    outResult.rgb *= g_diffuseColor.rgb;    
#endif

    
    {
        float4 Layer0 = g_diffuseColor;

#ifdef _MAP_DIFFUSE
        if (g_compositePixelOptions[2] == 0)
            Layer0 = tex2D( g_layer0, inData.uv0.xy);
#endif

        #ifdef _COMPOSITE_L0_ADD
            outResult += Layer0;
        #endif
        #ifdef _COMPOSITE_L0_MULTIPLY
            outResult *= Layer0;
        #endif
        #ifdef _COMPOSITE_L0_MULTIPLY2X
            outResult *= 2.f * Layer0;
        #endif
        #ifdef _COMPOSITE_L0_REPLACE
            outResult = Layer0;
        #endif
        
    }
    
#ifdef _COMPOSITE_2LAYERS   
    {
        float4 Layer1 = g_diffuseColor;
    
        if (g_compositePixelOptions[3] == 0)
            Layer1 = tex2D( g_layer1, inData.uv1.xy);
        
        #ifdef _COMPOSITE_L1_ADD
            outResult.rgb += Layer1.rgb;
        #endif
        #ifdef _COMPOSITE_L1_MULTIPLY
            outResult.rgb *= Layer1.rgb;
        #endif
        #ifdef _COMPOSITE_L1_MULTIPLY2X
            outResult.rgb *= 2.0f * Layer1.rgb;
        #endif
        #ifdef _COMPOSITE_L1_REPLACE
            outResult.rgb = Layer1.rgb;
        #endif
    }
#endif

#ifdef _COMPOSITE_LIGHTED
    #ifndef _MATERIAL_NOSPECULAR
        outResult.rgb += mySpecular * g_specularColor.rgb;
    #endif
#endif

    
    float fogValue;
    #ifdef _VERTICAL_FOG
        fogValue = saturate( (inData.vpos.y - g_verticalFogValues.x) / g_verticalFogValues.z);
        outResult.rgb = lerp(g_verticalFogColor.rgb, outResult.rgb, fogValue);
    #endif
    
    #ifdef _PIXEL_FOG
        ComputeFog(outResult,g_pixelFogColor.rgb,distance(g_cameraPos.xyz, inData.vpos.xyz),g_pixelFogOptions.x,g_pixelFogOptions.z);
    #endif
    
    /// Apply alpha from the material diffuse color
    float alphaValue = inData.color.a * g_diffuseColor.a;
    
    #ifdef _PIXELOPTION4
        float invAlphaValue = 1 - alphaValue;
        if (outResult.a < invAlphaValue)
        {           
            outResult.a = 0;
        }
        else if (outResult.a < invAlphaValue + 0.1)
        {   
            //outResult.rgb = 1;
            float factor = outResult.a -invAlphaValue;
            factor *= 10;
            outResult.a *=factor;
            //outResult.a -= invAlphaValue;
            //outResult.a /=  0.1;  
            //outResult.rgb  = outResult.a;
            //outResult.a = 1;      
        }
    #else
        outResult.a *= alphaValue;
    #endif

    outResult = saturate(outResult);

    #if defined(_RIM_FADING)
        outResult.a*=GetRimFading(g_cameraPos.xyz,inData.vpos.xyz,inData.normal,g_RimFading.y);
    #endif
}

#endif

#else //POINTSPRITES
//PointSprites code
struct CompositeSprite_InputVS
{
    float4 pos      : POSITION;
    float4 color    : COLOR0;   
    float2 size     : TEXCOORD0;
};

struct CompositeSprite_OutputVS
{
    float4 hpos         : POSITION;
    float4 color        : COLOR0;
    float  pointSize    : PSIZE;
};

struct CompositeSprite_InputPS
{   
    float4 color        : COLOR0;
#ifdef _XENON
    float2 t            : SPRITETEXCOORD;
#else
    float4 t            : TEXCOORD0;
#endif
};

#if defined(_MRT3) && !defined(_MRT2)
    #define _MRT2
#endif
#if defined(_MRT2) && !defined(_MRT1)
    #define _MRT1
#endif

struct Composite_OutputPS
{
#if !defined(_MRT)
    float4 color : COLOR0;
#else
    #if defined(_MRT_RT_0_1)
        float4 color : COLOR1;
    #elif defined(_MRT_RT_0_2)
        float4 color : COLOR2;
    #elif defined(_MRT_RT_0_3)
        float4 color : COLOR3;
    #else
        float4 color : COLOR0;
    #endif
    
    #if defined(_MRT1)
    #if defined(_MRT_RT_1_0)
        float4 color1 : COLOR0;
    #elif defined(_MRT_RT_1_2)
        float4 color1 : COLOR2;
    #elif defined(_MRT_RT_1_3)
        float4 color1 : COLOR3;
    #else
        float4 color1 : COLOR1;
    #endif
    #endif
    
    #if defined(_MRT2)
    #if defined(_MRT_RT_2_0)
        float4 color2 : COLOR0;
    #elif defined(_MRT_RT_2_1)
        float4 color2 : COLOR1;
    #elif defined(_MRT_RT_2_3)
        float4 color2 : COLOR3;
    #else
        float4 color2 : COLOR2;
    #endif
    #endif
    
    #if defined(_MRT3)
    #if defined(_MRT_RT_3_0)
        float4 color3 : COLOR0;
    #elif defined(_MRT_RT_3_1)
        float4 color3 : COLOR1;
    #elif defined(_MRT_RT_3_2)
        float4 color3 : COLOR2;
    #else
        float4 color3 : COLOR3;
    #endif
    #endif
#endif
};

sampler     g_layer0:register(s0);
sampler     g_layer1:register(s0);

float4      g_diffuseColor;
float4      g_ambientColor;
float4      g_emissiveColor;
float4      g_specularColor;

float4x4    g_matWorldViewProjection;
float4x4    g_matWorldView;
float4      g_cameraPos;
float4      g_screenSize;

#define g_bloomFactor g_emissiveColor.a

#if defined(_ALPHA_TEST)
float4      g_PixelAlphaTesting;
#endif

void main_VS( CompositeSprite_InputVS inVertex, out CompositeSprite_OutputVS outResult )
{
    outResult.color     = inVertex.color;

    /// Transform position from object to projection
    outResult.hpos      = Transform( g_matWorldViewProjection, inVertex.pos);
    
    float d = distance(inVertex.pos.xyz, g_cameraPos.xyz);
    outResult.pointSize = inVertex.size.x / d;
    outResult.pointSize *= g_screenSize.x;
}

#if defined(_MRT)
#define _MRT_DEFAULT_COLOR      float4(0,0,0,0)
#define _MRT_BLACK_COLOR        float4(0,0,0,1)

#ifndef _PIXEL_FOG
    float4      g_pixelFogOptions;
#endif

uniform float4      g_multilayerTextureOptions;

float4 getBloomOutput(float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;

    #if !defined(_POINTSPRITE)
    float4  ret = float4(0,0,0,1);
    ret.g = g_emissiveColor.a;
    #else
    float4  ret = float4(0,1,0,1);
    #endif

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }
    
    ret*=mulFactor;

    return ret;
}

#if !defined(_POINTSPRITE)
float4 getFocusBloomOutput(float opacity,float3 pos,float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;
    if(opacity>=1)
        mulFactor = 1;

    float4  ret = float4(0,0,0,opacity);
    ret.g = g_emissiveColor.a*opacity;

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }

    ret*=mulFactor;
    return ret;
}
#endif

#if defined(_MULTILAYER_CGFX)

//default output
float4 pso_MRT_default_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    #if !defined(_POINTSPRITE)
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
    #else
    return getBloomOutput(IN.uv.xy,g_diffuseMap);
    #endif
}

float4 pso_MRT_focusBloom_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uvcoords.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

#endif

//default output
#if defined(_COMPOSITE_CGFX)
#ifndef _POINTSPRITE
float4 pso_MRT_default_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(Composite_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(Composite_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_layer0);
}

#else
float4 pso_MRT_default_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return getBloomOutput(IN.uv.xy,g_layer0);
}
#endif
#endif

#if defined(_MRT3) && !defined(_MRT2)
#define _MRT2
#endif

#if defined(_MRT2) && !defined(_MRT1)
#define _MRT1
#endif

#if defined(_MRT1) && !defined(_MRT1_OUTMETHOD)
    #define _MRT1_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT2) && !defined(_MRT2_OUTMETHOD)
    #define _MRT2_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT3) && !defined(_MRT3_OUTMETHOD)
    #define _MRT3_OUTMETHOD     pso_MRT_default_output
#endif
#endif

void main_PS( CompositeSprite_InputPS inData, out Composite_OutputPS outResult )
{   
    outResult.color.rgb = inData.color.rgb * g_diffuseColor.rgb;
    outResult.color.a = inData.color.a * g_diffuseColor.a;
    
    float2 uv = inData.t;
    
    float4 texColor = tex2D( g_layer0, uv);
    
        #ifdef _PIXELOPTION2
            outResult.color.rgb += texColor.rgb;
        #endif
        #ifdef _PIXELOPTION3
            outResult.color *= texColor;
        #endif
        #ifdef _COMPOSITE_L0_MULTIPLY2X
            outResult.color *= 2 * texColor;
        #endif
        #ifdef _COMPOSITE_L0_REPLACE
            outResult.color = texColor;
        #endif
    
    /*
    /// Apply emissive material color
    /// Then saturate the color
    OUT.color.rgb += g_emissiveColor.rgb;
    OUT.color.rgb = saturate(OUT.color.rgb);
    
    #if defined (_VERTICAL_FOG ) || defined (_PIXEL_FOG)
        OUT.color.rgb = lerp(IN.fog, OUT.color.rgb, IN.fog.a);
    #endif
    */

    #if defined(_MRT1)
        outResult.color1 = _MRT1_OUTMETHOD(inData,OUT.color);
    #endif

    #if defined(_MRT2)
        outResult.color2 = _MRT2_OUTMETHOD(inData,OUT.color);
    #endif

    #if defined(_MRT3)
        outResult.color3 = _MRT3_OUTMETHOD(inData,OUT.color);
    #endif
    
    #if defined(_ALPHA_TEST)
        clip(g_PixelAlphaTesting.x - outResult.color.a);
    #endif  
}

#endif

// If the use os axis aligned box for a light has been defined, but not the type of light we asume that it corresponds to an ambient light
#define _MULTILAYER_CGFX
 
 
// In the case low, med or high shadows are used, we are using shadows!
#if defined (_SHADOW_LOW) || defined (_SHADOW_MED) || defined(_SHADOW_HI)
    #define __USE_SHADOWMAP
#endif

#ifdef _PIXELOPTION3 
    #define BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA
#endif
  
//////////////////////////////////////
// VERTEX SHADER CONSTANTS
#ifdef _VERTEX_SHADER
    uniform float4x4    g_matWorld, g_matWorldView, g_matWorldViewProjection;

    float4 g_textureTransform0;
    float4 g_textureTransform1;

    float4 g_textureTransformExt0;
    float4 g_textureTransformExt1;

    #ifdef _LIGHT0_SPOT 
        float4x4 g_matTexture2;
    #endif

    #ifdef _LIGHT1_SPOT 
        float4x4 g_matTexture3;
    #endif

    #if defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_SPHEREVIEW)
        float3x3 g_matView;
    #endif

    #if defined(_USE_TAPER)
        uniform float4x4 g_matViewProjection;
    #endif

#elif defined(_MAP_EMISSIVE) || defined(_EMISSIVE_FLIPBOOK)
    float4 g_textureTransform5;
#endif

uniform float4      g_cameraPos;

#ifdef _PS3_VSCLIPPLANE0
    uniform float4  g_ps3ClipPlane0;
#endif

#ifdef _POINTSPRITE
    float4      g_screenSize;
#endif

////////////////////////////////////////
// MATERIAL INFO
uniform float4      g_diffuseColor;
uniform float4      g_ambientColor;
uniform float4      g_emissiveColor;
uniform float4      g_specularColor;
uniform float4      g_enviromentColor;

#define g_bloomFactor               g_emissiveColor.a

///////////////////////////////////////
// FX INFO
uniform float4      g_zBlurOptions;

//////////////////////////////////////
// LIGHTING
//////////////////////////////////////

//////////////////////////////////////
// LIGHTING INFO
float4      g_ambient;

#if defined(_LIGHT0_POINT) || defined(_LIGHT0_DIRECTIONAL) || defined(_LIGHT0_SPOT)
uniform float4      g_lightDirection0;
uniform float4      g_lightPosition0;
uniform float4      g_lightColor0;
uniform float4      g_lightSpecular0;
#endif

#if defined(_LIGHT1_POINT) || defined(_LIGHT1_DIRECTIONAL) || defined(_LIGHT1_SPOT)
uniform float4      g_lightDirection1;
uniform float4      g_lightPosition1;
uniform float4      g_lightColor1;
uniform float4      g_lightSpecular1;
#endif

#if defined(_LIGHT2_POINT) || defined(_LIGHT2_DIRECTIONAL)
uniform float4      g_lightDirection2;
uniform float4      g_lightPosition2;
uniform float4      g_lightColor2;
uniform float4      g_lightSpecular2;
#endif

#if defined(_LIGHT3_POINT) || defined(_LIGHT3_DIRECTIONAL)
uniform float4      g_lightDirection3;
uniform float4      g_lightPosition3;
uniform float4      g_lightColor3;
uniform float4      g_lightSpecular3;
#endif

#if defined(_RIM_FADING)
uniform float4      g_RimFading;
#endif

#if defined(_USE_TAPER)
uniform float4      g_TaperOrigin;
uniform float4      g_TaperDir;

//Returns tapered pos
float3 TaperVert(float3 worldPos)
{
    float3 taperOrigin = g_TaperOrigin.xyz; 
    float3 taperDir = g_TaperDir.xyz;
    float taperMaxDist = g_TaperOrigin.w;
    float taperFactor = g_TaperDir.w;

    float3 from = worldPos-taperOrigin;
    float proj = dot(from,taperDir);
    if (proj <= 0)
        return taperOrigin;
    float3 projVec = proj*taperDir;
    float3 delta = (from-projVec);
    float len = length(delta);
    
    float3 newDelta = delta - lerp(0,len,saturate(taperFactor*(taperMaxDist-proj)))*delta/len;
    float3 newPos = taperOrigin+projVec+newDelta;
    return newPos;
}
#endif

//////////////////////////////////////
// MATRIX MULTIPLICATION
//////////////////////////////////////
float3 Transform(float3x3 mat, float3 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif
}

float4 Transform(float4x4 mat, float4 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

float2 Transform(float2x2 mat, float2 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

//this conversion will not deal with renormalizations because is a bad way to handle bad data passing to the shader.
//the main problem is that cg-compiler isn't as smart as hlsl-compiler dealing with already normalized vectors
float3x3 GetWorldToTangentMatrix(float3x3 worldmtx,float3 tangent, float3 normal)
{
    float3x3 worldToTangent = 0;
    worldToTangent[0] = normalize(Transform(worldmtx, tangent));
    worldToTangent[2] = normalize(Transform(worldmtx, normal));
    worldToTangent[1] = normalize(cross(worldToTangent[0], worldToTangent[2]));    

    return worldToTangent;
}

float4 TransformPlanarReflection(float4 inPos)
{
    float4x4    matTexScale = 0;

#if !defined(_GCM)
    matTexScale._m00 = 0.5f;
    matTexScale._m11 =  -.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m03 = 0.5f; 
    matTexScale._m13 = 0.5f;
    matTexScale._m23 = 1.0f; 
    matTexScale._m33 = 1.0f;
#else
    matTexScale._m00 = 0.5f;
    matTexScale._m11 = -0.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m30 = 0.5f; 
    matTexScale._m31 = 0.5f;
    matTexScale._m32 = 1.0f; 
    matTexScale._m33 = 1.0f;
#endif

    return Transform(matTexScale,inPos);
}


//////////////////////////////////////
// SKINNING
//////////////////////////////////////

#if defined(_VERTEX_SHADER) && defined(_USE_SKINMATRIX)
uniform float4x4    g_skinMatrix[_MAXBONES];        ///< 128 Registers for skin bones

struct SKINVERTEX
{
    float4 P;
    float3 N;
    float3 T;
};

SKINVERTEX SkinVertex(float3 p, float3 n, float3 t, float4 indices, float4 weights)
{
    SKINVERTEX Out = (SKINVERTEX) 0;
    for(int i = 0; i < 4; i++)
    {
        Out.P.xyz += Transform(g_skinMatrix[indices.x], float4(p,1)).xyz * weights.x;
        Out.N += (float3)(Transform((float3x3) g_skinMatrix[indices.x], n) * weights.x);

        #if !defined(SH_VERSION_SH1)
        Out.T += (float3)(Transform((float3x3) g_skinMatrix[indices.x], t) * weights.x);
        #endif

        indices.xyzw = indices.yzwx;
        weights.xyzw = weights.yzwx;
    }

    Out.P.w = 1;
    Out.N = (float3)normalize(Out.N);
    
    #if !defined(SH_VERSION_SH1)
    Out.T = (float3)normalize(Out.T);
    #endif

    return Out;
}

#endif

//////////////////////////////////////
// END SKINNING
//////////////////////////////////////

#ifdef _VERTEX_SHADER

float3 GetUVCoordinate3L0(float3 position, float3 normal, float3 viewer)
{
    #ifdef _UV0_AUTO_POSITION
        return position;
    #elif defined(_UV0_AUTO_REFLECTION)
        return (2.f * dot(viewer,normal) * normal - viewer) * .5f + .5f;
    #elif defined(_UV0_AUTO_NORMAL)
        return normal;
    #elif defined(_UV0_AUTO_SPHERE)
        return normal * .5f + .5f;
    #elif defined(_UV0_AUTO_SPHEREVIEW)
        float3 normalViewSpace = Transform(g_matView, normal);
        return float3(normalViewSpace.x, -normalViewSpace.y, 1.0f) * .5f + .5f;
    #else
        return normal;
    #endif  
}

float3 GetUVCoordinate3L1(float3 position, float3 normal, float3 viewer)
{
    #ifdef _UV1_AUTO_POSITION
        return position;
    #elif defined(_UV1_AUTO_REFLECTION)
        return (2.f * dot(viewer,normal) * normal - viewer) * .5f + .5f;
    #elif defined(_UV1_AUTO_NORMAL)
        return normal;
    #elif defined(_UV1_AUTO_SPHERE)
        return normal * .5f + .5f;
    #elif defined(_UV1_AUTO_SPHEREVIEW)
        float3 normalViewSpace = Transform(g_matView, normal);
        return float3(normalViewSpace.x, -normalViewSpace.y, 1.0f) * .5f + .5f;
    #else
        return normal;
    #endif  
}

#endif

#ifdef _VERTEX_SHADER

/// FOR PER VERTEX SHADERS
struct Multilayer_InputVS
{
    float4 pos      : POSITION;         ///< Vertex position
    
#ifdef _USE_SKINMATRIX
    float4 weight   : BLENDWEIGHT;      ///< Weights values for skinning
    float4 indices  : BLENDINDICES;     ///< Index of bones for skinning
#endif

#ifdef _HAS_NORMAL
    float3 normal   : NORMAL;           ///< Vertex Normal
#endif

#ifdef _HAS_TANGENT3
    float3 tangent  : TANGENT;          ///< Vertex tangent, for use to map to tangent space normal maps
#endif

#ifdef _HAS_TANGENT
    float4 tangent  : TANGENT;          ///< Vertex tangent, for use to map to tangent space normal maps
#endif

#ifdef _HAS_COLOR
    float4 color    : COLOR0;           ///< Diffuse color of the vertex
#endif

#ifdef _HAS_UV0
    float2 uv0      : TEXCOORD0;        ///< UV Coordinates for diffuse, enviroment and normal map
#endif

#ifdef _HAS_UV1
    float2 uv1      : TEXCOORD1;        ///< UV Coordinates for light map
#endif

#ifdef _HAS_UV2
    float2 uv2      : TEXCOORD2;
#endif
};

#endif


struct MultilayerPVL_OuputVS
{
    float4 hpos         : POSITION;     ///< Clip space transformed vertex position
    float4 color        : COLOR0;       ///< Vertex color
    
#ifndef _POINTSPRITE        
    float4 vpos         : TEXCOORD0;    ///< Position of the vertex in world space, and shadowprojection distance
    float3 uv0          : TEXCOORD1;    ///< UV Coordinates used by the diffuse texture, enviroment mask, and the normal map
    float3 uv1          : TEXCOORD2;    ///< UV Coordinates used by the enviroment map
    float2 uv2          : TEXCOORD3;    ///< UV Coordinates used by the light map   
    float3  normal      : TEXCOORD4;    ///< Vertex normal
    float3  view            : TEXCOORD5;    ///< View direction to the vertex

    #ifdef __USE_SHADOWMAP
        float4 shadowProjection : TEXCOORD6;    ///< Shadow map projection
    #endif

    #ifdef _PS3_VSCLIPPLANE0
        float oClip0        : CLP0;
    #endif

#else //POINTSPRITE code
    float   pointSize   : PSIZE;
#endif
};

struct MultilayerPVLSpot_OuputVS
{
    float4 hpos             : POSITION;     ///< Clip space trasnformed vertex
    float4 color            : COLOR0;       ///< Vertex color   
    float3 uv0              : TEXCOORD0;    ///< UV Coordinates used by the diffuse texture, enviroment mask, and the normal map
    float3  normal          : TEXCOORD1;    ///< Vertex normal
    float3  view                : TEXCOORD2;    ///< View direction to the vertex
    float3 vpos             : TEXCOORD3;    ///< Position of the vertex in world space  
    float4 lightDir0        : TEXCOORD4;    ///< Direction of light 0

    #ifdef _LIGHT0_SPOT
        float4 spotProjection1  : TEXCOORD5;    ///< Shadow map projection
    #endif

    #ifdef _LIGHT1_SPOT
    #undef __USE_SHADOWMAP                      // [BP] 2 spot lights do not allow the use of shadow maps (Using texcoord7)
        float4 lightDir1        : TEXCOORD6;    ///< Direction of light 1
        float4 spotProjection2  : TEXCOORD7;    ///< Shadow map projection
    #endif

    #if defined(__USE_SHADOWMAP)
        float4 shadowProjection : TEXCOORD7;    ///< Shadow map projection
    #endif

    #ifdef _PS3_VSCLIPPLANE0
        float oClip0            : CLP0;
    #endif
};

struct MultilayerPPL_OutputVS
{
    float4 hpos         : POSITION;     ///< Clip space transformed vertex position
    float4 color        : COLOR0;       ///< Diffuse color
    float4 uvcoords     : TEXCOORD0;    ///< Uv coordinates of diffuse and enviroment maps
    float4 vpos         : TEXCOORD1;    ///< Position in world space and lightspace depth
    float4 lightDir0    : TEXCOORD2;    ///< Direction of light 0
    float4 lightDir1    : TEXCOORD3;    ///< Direction of light 1
    float4 lightDir2    : TEXCOORD4;    ///< Direction of light 2 
    float4 lightDir3    : TEXCOORD5;    ///< Direction of light 3
    float3  viewDir     : TEXCOORD6;    ///< View direction to the vertex (tangent space)

    #if defined(__USE_SHADOWMAP)
        float4 shadowProjection : TEXCOORD7;    ///< Shadow map projection
    #endif

    #ifdef _PS3_VSCLIPPLANE0
        float oClip0        : CLP0;
    #endif
};

struct MultilayerPPLSpot_OutputVS
{
    float4 hpos             : POSITION; 
    float4 color            : COLOR0;
    
    float3 uv0              : TEXCOORD0;        ///< UV Coordinates used by the diffuse texture, enviroment mask, and the normal map
    float3 vpos             : TEXCOORD1;        ///< Position in world space of the vertex
    
    float4 lightDir0        : TEXCOORD2;        ///< Direction of light 0
#ifdef _LIGHT0_SPOT
    float4 spotProjection1  : TEXCOORD3;        ///< Shadow map projection
#endif
#ifdef _LIGHT1_SPOT
#undef __USE_SHADOWMAP
    float4 lightDir1        : TEXCOORD4;        ///< Direction of light 1
    float4 spotProjection2  : TEXCOORD5;        ///< Shadow map projection
#endif

    float3  view                : TEXCOORD6;        ///< Vire direction vector

#if defined(__USE_SHADOWMAP)
    float4 shadowProjection : TEXCOORD7;    ///< Shadow map projection
#endif

#ifdef _PS3_VSCLIPPLANE0
    float oClip0            : CLP0;
#endif
};

struct MultilayerPVL_OutputPS
{
#if !defined(_MRT)
    float4 color : COLOR0;
#else
    #if defined(_MRT_RT_0_1)
        float4 color : COLOR1;
    #elif defined(_MRT_RT_0_2)
        float4 color : COLOR2;
    #elif defined(_MRT_RT_0_3)
        float4 color : COLOR3;
    #else
        float4 color : COLOR0;
    #endif
    
    #if defined(_MRT1)
    #if defined(_MRT_RT_1_0)
        float4 color1 : COLOR0;
    #elif defined(_MRT_RT_1_2)
        float4 color1 : COLOR2;
    #elif defined(_MRT_RT_1_3)
        float4 color1 : COLOR3;
    #else
        float4 color1 : COLOR1;
    #endif
    #endif
    
    #if defined(_MRT2)
    #if defined(_MRT_RT_2_0)
        float4 color2 : COLOR0;
    #elif defined(_MRT_RT_2_1)
        float4 color2 : COLOR1;
    #elif defined(_MRT_RT_2_3)
        float4 color2 : COLOR3;
    #else
        float4 color2 : COLOR2;
    #endif
    #endif
    
    #if defined(_MRT3)
    #if defined(_MRT_RT_3_0)
        float4 color3 : COLOR0;
    #elif defined(_MRT_RT_3_1)
        float4 color3 : COLOR1;
    #elif defined(_MRT_RT_3_2)
        float4 color3 : COLOR2;
    #else
        float4 color3 : COLOR3;
    #endif
    #endif
#endif
};

//////////////////////////////////////
// LIGHTING FUNCTIONS
//////////////////////////////////////
/*
CalculateSpecularLighting
Calculates the specular lighting for an interest point
*/
float3 CalculateSpecularLighting(
            in float3 lightDirection,           ///< Direction of the light MUST BE NORMALIZED!
            in float3 lightSpecularColor,       ///< Specular color
            in float3 normalVector,             ///< Normal vector of the intereset point
            in float3 viewVector                ///< View vector of the interest point
            )
{
    float3 Half = normalize( lightDirection + viewVector);
    return lightSpecularColor.xyz * pow(saturate( dot( Half, normalVector) ), g_specularColor.a);
}

/*
CalculatePointLightAttenuation
Calculates the attenuation of a point light on a surface point
*/
float CalculatePointLightAttenuation(
     in float3  iLightDirection,            ///< Direction NOT NORMALIZED, from the point to the light position  
     float      iLightInverseRange          ///< Inverse range (1/r) of the point light  
     )
{
    float3 attenuatedLightDirection = iLightDirection * iLightInverseRange;
    return saturate ( 1.0f - dot (attenuatedLightDirection, attenuatedLightDirection));
}
     


void LightSpot_VS(float3 iDir, float invRange, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir);
    //oFactor = ( 1.0f - (oFactor  / Range) );  
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));                    
}

void LightSpot_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = iDir;
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;
    
    oD += lightColor * iD * saturate(fNDotL) * Factor;
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += Factor * lightColor * iS.xyz * pow(saturate(dot(Half,normal)), iS.a);
    #endif
}

/*
GetPointLightDirectionInTangentSpace
Retrieves the direction of a point light in tangent space
*/
float3 GetPointLightDirectionInTangentSpace( 
        float3 lightPosition,                   ///< Light position in world space
        float3 vertexPosition,                  ///< Vertex position in world space
        float3x3 worldToTangentTransform        ///< World to Tangent space transformation
        )
{
    float3 lightDir = lightPosition - vertexPosition;
    lightDir = mul(worldToTangentTransform, lightDir);
    return lightDir;
}

/*
GetPointLightDirectionInWorldSpace
Calculates the point light direction in world space
*/
float3 GetPointLightDirectionInWorldSpace(
        float3 lightPosition,                   ///< Light position in world space
        float3 vertexPosition                   //< Vertex position in world space
        )
{
    return lightPosition - vertexPosition;
}

void OutLightDirSpotPPL(float3 iDir, float invRange, float3x3 TBN, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir.xyz);
    //oFactor = ( 1.0f - (oFactor  * invRange) );   
    oDir.xyz = mul(TBN, oDir.xyz);  
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));
}

void OutLightDirSpotPVL(float3 iDir, float invRange, out float3 oDir, out float oFactor)
{
    oDir.xyz = iDir;
    //oFactor = length(iDir.xyz);
    //oFactor = ( 1.0f - (oFactor  / Range) );                      
    oFactor = saturate ( 1.0f - dot (iDir * invRange, iDir * invRange));
}

void LightDirectional_PPL_PS(float3 iDir, float3 n, float3 v, float3 iD, float3 iS, inout float3 oD, inout float3 oS)
{
    float3 fvLightDir = normalize(iDir);
    float fNDotL = dot(n, fvLightDir);      
    oD += iD * saturate(fNDotL);

    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir + v);
        oS.xyz += iS.xyz * pow(saturate(dot(Half, n)), g_specularColor.a);
    #endif
}

/*
AddPointLightContributionTangentSpace
Adds the contribution diffuse and specular lighting of a point light to a point of a surface
*/
void AddPointLightContributionTangentSpace(
    in float3       iLightDirectionTangentSpace,        ///< Direction to the light from the 3d point in tangent space
    in float3       iLightPositionWorldSpace,           ///< Position of the point light in world space
    in float        iLightInverseRange,                 ///< Inverse range of the point light (1/r)
    in float3       iLightDiffuseColor,                 ///< Diffuse color of the light
    in float3       iLightSpecularColor,                ///< Specular color of the light
    in float3       iPointNormalTangentSpace,           ///< Normal on the 3d point in tangent space
    in float3       iPointViewTangentSpace,             ///< View vector on the 3d point in tangent space
    in float3       iPointPositionWorldSpace,           ///< Position of the 3d point in world space
    inout float3    ioAcumulatedDiffuseLight,           ///< Acumulated diffuse light
    inout float3    ioAcumulatedSpecularLight           ///< Acumulated specular light
    )
{
    // Calculate attenuation of the spot light
    float lightAttenuation = CalculatePointLightAttenuation(iLightPositionWorldSpace - iPointPositionWorldSpace, iLightInverseRange );
    
    // Calculate diffuse lighting contribution
    float3 lightDirectionNormalized = normalize( iLightDirectionTangentSpace );
    float fNDotL = dot(iPointNormalTangentSpace, lightDirectionNormalized);     
    ioAcumulatedDiffuseLight += iLightDiffuseColor * saturate(fNDotL) * lightAttenuation;
    
    // Calculate specular lighting contribution
    #ifndef _MATERIAL_NOSPECULAR
        ioAcumulatedSpecularLight += lightAttenuation * 
            CalculateSpecularLighting(lightDirectionNormalized, iLightSpecularColor, iPointNormalTangentSpace, iPointViewTangentSpace );
    #endif
}

void LightPoint_PPL_PS(float3 iDir, float3 n, float3 v, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS)
{
    float3 fvLightDir = normalize(iDir);
    float fNDotL = dot(n, fvLightDir);      
    oD += iD * saturate(fNDotL) * Factor;
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+v);
        oS.rgb += Factor * iS.xyz * pow(saturate( dot(Half,n) ), g_specularColor.a);
    #endif
}

void LightSpot_PPL_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = normalize(iDir);        
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;            
    oD += saturate( lightColor * iD * saturate(fNDotL) * Factor );
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += saturate( lightColor * Factor * iS.xyz * pow(saturate(dot(Half,normal)), g_specularColor.a) );
    #endif
}
    
void LightDirectional_PVL_PS(float3 iDir, float3 normal, float3 view, float3 iD, float  transColor, float3 iS, inout float3 oD, inout float3 oS)
{
    
    float fNDotL = dot(normal, iDir);       
    oD += iD.rgb * saturate(fNDotL);
    
    #ifdef _TRANSLUCENCY
            float fNDotL2 = dot(-normal, iDir);     
            oD += iD.rgb * saturate(fNDotL2) * transColor;
    #endif
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(iDir + view);   
        oS += iS.xyz * pow( saturate(dot(Half,normal)), g_specularColor.a);
    #endif
}

/*
AddPointLightContributionWorldSpace
Adds the contribution diffuse and specular lighting of a point light to a point of a surface
*/
void AddPointLightContributionWorldSpace(
    in float3       iLightPosition,             ///< Light position in world space
    in float        iLightInverseRange,         ///< Inverse range of the point light (1/r)
    in float3       iLightDiffuseColor,         ///< Diffuse color of the light
    in float3       iLightSpecularColor,        ///< Specular color of the light
    in float3       iPointNormal,               ///< Normal of the 3d point in world space
    in float3       iPointView,                 ///< View vector of the 3d point in world space
    in float3       iPointPosition,             ///< Poisition of the 3d point in worls space
    inout float3    ioAcumulatedDiffuseLight,   ///< Acumulated diffuse lighting
    inout float3    ioAcumulatedSpecularLight   ///< Acumulated specular lighting
    )
{
    // Determiate the light direction, used for attenuation and light contribution
    float3 lightDirection = iLightPosition - iPointPosition;

    // Calculate attenuation of the spot light
    float lightAttenuation = CalculatePointLightAttenuation(lightDirection, iLightInverseRange);
    
    // Calculate diffuse lighting contribution
    lightDirection = normalize( lightDirection );
    float fNDotL = dot(iPointNormal, lightDirection);       
    ioAcumulatedDiffuseLight += iLightDiffuseColor * saturate(fNDotL) * lightAttenuation;
    
    // Calculate specular lighting contribution
    #ifndef _MATERIAL_NOSPECULAR
        ioAcumulatedSpecularLight += lightAttenuation * 
            CalculateSpecularLighting(lightDirection, iLightSpecularColor, iPointNormal, iPointView);
    #endif
}

void LightSpot_PVL_PS(float3 iDir, float3 normal, float3 view, float Factor, float3 iD, float4 iS, inout float3 oD, inout float3 oS, sampler2D spotMap, float4 spotTex)
{
    float3 fvLightDir = iDir;
    float fNDotL = dot(normal, fvLightDir);     

    float3 lightColor = tex2Dproj(spotMap, spotTex).rgb;            
    oD += lightColor * iD * saturate(fNDotL) * Factor;      
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += lightColor * Factor * iS.xyz * pow(saturate(dot(Half,normal)), g_specularColor.a);
    #endif
}


//////////////////////////////////////
// END LIGHTING
//////////////////////////////////////

//////////////////////////////////////
// SHADOWMAPPING
//////////////////////////////////////
#ifdef __USE_SHADOWMAP

uniform float4x4    g_matTextureProjection;
uniform float4      g_shadowmapOptions;
uniform float4      g_texelSize89;

#define     g_ShadowmapFactor   (1-g_shadowmapOptions.x)    /// default 0.0
#define     g_ShadowmapZBias    (g_shadowmapOptions.y)      /// default -0.001

uniform sampler2D   g_shadowMap         : register(s9);
uniform samplerCUBE g_shadowCubeMap     : register(s9);

////////////////////////////////////
// DIRECTIONAL
float SampleShadowTest(float4 ShadowTexC)
{   
    #if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI
        return tex2D(g_shadowMap, ShadowTexC.xy).r >= ShadowTexC.z;     
    #else   //nVidia
        return tex2Dproj(g_shadowMap, ShadowTexC).r;
    #endif  
}

float GetShadowDirectional(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.f - ShadowTexC.y;

#ifdef _PS3
    ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _XENON
    ShadowTexC.xyz = ShadowTexC.xyz / ShadowTexC.w;
    
    // [BP] On xbox360 we are getting projected distances that are higher than 1
    // as they are not being cut by the far plane of the light frustum
    // still we need to study more this effect, even check if it can be done on vertex
    // shader stage to save gpu process
    ShadowTexC.z = min(1,ShadowTexC.z);     // Check that z the minimum value to 1
#endif
    
#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
    
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.w = 1;
            
    #if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)
        return saturate(SampleShadowTest(ShadowTexC) + g_ShadowmapFactor);
    #else

        float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 2;
        float4 tY = float4(0, g_texelSize89.w, 0, 0) * 2;
        float accum = 0;
 
        #if defined(_SHADOW_MED)
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY *  .5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY *  .5);
            return saturate((accum/4.f) + g_ShadowmapFactor);
        #elif defined(_SHADOW_HI)
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  1);  
            return saturate((accum/9.f) + g_ShadowmapFactor);
        #else
            return 1;
        #endif
    #endif  
}

/////////////////////////////////
// SPOT
//[VC]: why this is just a copy paste from spotdirectional???
float GetShadowSpotSample(float4 ShadowTexC)
{
    float shadow;

#if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI

    float a = tex2D(g_shadowMap, ShadowTexC.xy).r > ShadowTexC.z;
    float b = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, 0)).r > ShadowTexC.z;
    float c = tex2D(g_shadowMap, ShadowTexC.xy + float2(0, g_texelSize89.w)).r > ShadowTexC.z;
    float d = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, g_texelSize89.w)).r > ShadowTexC.z;

#if defined(SH_VERSION_SH2)
    return a;
#endif
    
    // transform to texel space
    float2 texelpos = (1.f/g_texelSize89.zw) * ShadowTexC;
    
    // Determine the lerp amounts           
    float2 lerps = frac( texelpos );

    // lerp between the shadow values to calculate our light amount
    shadow = lerp( lerp( a, b, lerps.x ),
                   lerp( c, d, lerps.x ),
                   lerps.y );       
    return shadow;

#else   //nVidia

    shadow = tex2Dproj(g_shadowMap, ShadowTexC).r;

#endif
    
    return shadow;
}

float GetShadowSpot(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy / TexCoords.w + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.0f - ShadowTexC.y;

    //not needed for spot lights
#ifdef _PS3
    //ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
        
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.z /= ShadowTexC.w;

    ShadowTexC.w = 1;
            
#if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)

    return saturate(GetShadowSpotSample(ShadowTexC) + g_ShadowmapFactor);
    
#endif

    float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 1;
    float4 tY = float4(0, g_texelSize89.w, 0, 0) * 1;

    float accum = 0;

#if defined(_SHADOW_MED)
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY *  .5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY *  .5); 
    return saturate((accum/4.f) + g_ShadowmapFactor);
#endif
    
#if defined(_SHADOW_HI)
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  1);
    return saturate((accum/9.f) + g_ShadowmapFactor);
#endif

    return 1;
}


/////////////////////////////////
// POINT

float GetShadowPointSample(float3 Pos)
{
    float shadow = 1;

#ifdef _LIGHT0_POINT
    shadow = texCUBE(g_shadowCubeMap, Pos.xyz-g_lightPosition0.xyz).r > (length(Pos.xyz-g_lightPosition0.xyz) * g_lightPosition0.w) + g_ShadowmapZBias;
#endif

    return shadow;
}

float GetShadowPoint(float3 Pos)
{
    return saturate(GetShadowPointSample(Pos) + g_ShadowmapFactor);
}

#endif
//////////////////////////////////////
// END SHADOWMAPPING
//////////////////////////////////////


float GetRimFading(float3 CamPos,float3 FragmentWorldPos,float3 Normal,float InvThreshold)
{
    float3 nCminP = normalize(CamPos.xyz-FragmentWorldPos.xyz);
    float NdotCmP = dot(Normal,nCminP);
    return saturate(NdotCmP*InvThreshold);
}

void ComputeFog(inout float4 PixelColor,float3 FogColor,float DistancePixelToCamera,float MinDistanceToFog,float MaxMinusMinDistanceToFog)
{
#if defined(_PIXEL_FOG)
    float CamMinusFogMin = (DistancePixelToCamera-MinDistanceToFog);
    float FogFactor  = 1-saturate(CamMinusFogMin/MaxMinusMinDistanceToFog);
    #if !defined(_ADDITIVE_PIXEL_FOG)
        PixelColor.rgb = lerp(FogColor, PixelColor.rgb, FogFactor);
    #elif defined(_ADDITIVE_PIXEL_FOG)
        PixelColor.rgb*=FogFactor;
        clip(MaxMinusMinDistanceToFog-CamMinusFogMin);
    #endif
#endif
}


///////////////////////////////////////////////////////////////
//VERTEX SHADERS
///////////////////////////////////////////////////////////////
#ifdef _VERTEX_SHADER


#ifdef _PERPIXEL_LIGHTING
    #ifdef _LIGHT0_SPOT
        #define MULTILAYER_OUTPUT_VS        MultilayerPPLSpot_OutputVS
        #define MULTILAYER_MAIN_VS      MultilayerPPLSpot_MainVS
    #else
        #define MULTILAYER_OUTPUT_VS        MultilayerPPL_OutputVS
        #define MULTILAYER_MAIN_VS      MultilayerPPL_MainVS
    #endif
#else
    #ifdef _LIGHT0_SPOT
        #define MULTILAYER_OUTPUT_VS        MultilayerPVLSpot_OuputVS
        #define MULTILAYER_MAIN_VS      MultilayerPVLSpot_MainVS
    #else
        #define MULTILAYER_OUTPUT_VS        MultilayerPVL_OuputVS
        #define MULTILAYER_MAIN_VS      MultilayerPVL_MainVS
    #endif
#endif

void MultilayerPPL_MainVS(          Multilayer_InputVS  inVertex,out    MultilayerPPL_OutputVS      outResult);
void MultilayerPPLSpot_MainVS(      Multilayer_InputVS  inVertex,out    MultilayerPPLSpot_OutputVS  outResult);
void MultilayerPVL_MainVS(          Multilayer_InputVS  inVertex,out    MultilayerPVL_OuputVS       outResult);
void MultilayerPVLSpot_MainVS(      Multilayer_InputVS  inVertex,out    MultilayerPVLSpot_OuputVS   outResult);

void main_VS( Multilayer_InputVS inVertex, out MULTILAYER_OUTPUT_VS outResult )
{
    MULTILAYER_MAIN_VS(inVertex, outResult);
}

///////////////////////////////////////////////
// Omni & Direct Per Pixel Vertex Shader
///////////////////////////////////////////////
void MultilayerPPL_MainVS( Multilayer_InputVS inVertex, out MultilayerPPL_OutputVS outResult)
{
    outResult = (MultilayerPPL_OutputVS) 0;
        
    #ifdef _HAS_NORMAL
        float3 tempNormal = normalize(inVertex.normal.xyz);
    #else 
        float3 tempNormal = float3(0,0,1);
    #endif
    
    #if defined(_HAS_TANGENT3) || defined(_HAS_TANGENT)
        float3 tempTangent = normalize(inVertex.tangent.xyz);
    #else
        float3 tempTangent = float3(1,0,0);
    #endif
    
    #ifdef _HAS_COLOR
        outResult.color = inVertex.color;
    #else
        outResult.color = float4(1,1,1,1);
    #endif

    /// Determinate the vertex position, normal and tangent from skinning
#ifdef _USE_SKINMATRIX  
    SKINVERTEX v = SkinVertex(inVertex.pos.xyz, tempNormal, tempTangent, inVertex.indices, inVertex.weight);    
    float4 position = v.P;
    float3 normal   = v.N;
    float3 tangent  = v.T;  
#else
    float4 position = float4(inVertex.pos.xyz,1);
    float3 normal   = tempNormal; 
    float3 tangent  = tempTangent;
#endif


    /// Transform the position and the normal to projection space
    outResult.vpos  = Transform(g_matWorld, position);
#if defined (_USE_TAPER)
    outResult.vpos  = float4(TaperVert(outResult.vpos.xyz),1);
    outResult.hpos  = Transform(g_matViewProjection, outResult.vpos);
#else
    outResult.hpos  = Transform(g_matWorldViewProjection, position);
#endif
        

#ifdef _PS3_VSCLIPPLANE0
    outResult.oClip0    = dot(outResult.vpos, g_ps3ClipPlane0);
#endif

    /// Compute the tangent transformation matrix
    float3x3 worldToTangent = GetWorldToTangentMatrix((float3x3)g_matWorld,tangent,normal);

#ifdef _HAS_TANGENT
    worldToTangent[1] *= inVertex.tangent.w;
#endif
    

    /// Calculate lighting for directional lights, these must be transformed into tangent space
    #ifdef _LIGHT0_DIRECTIONAL      
        outResult.lightDir0.xyz = -mul(worldToTangent, g_lightDirection0.xyz);
        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, position);
        #endif
    #endif
    
    #ifdef _LIGHT1_DIRECTIONAL      
        outResult.lightDir1.xyz = -mul(worldToTangent, g_lightDirection1.xyz);
    #endif
    
    #ifdef _LIGHT2_DIRECTIONAL      
        outResult.lightDir2.xyz = -mul(worldToTangent, g_lightDirection2.xyz);
    #endif
    
    #ifdef _LIGHT3_DIRECTIONAL      
        outResult.lightDir3.xyz = -mul(worldToTangent, g_lightDirection3.xyz);
    #endif
    
    /// Calculate lighting for point lights
    #ifdef _LIGHT0_POINT
        outResult.lightDir0.xyz = GetPointLightDirectionInTangentSpace(g_lightPosition0.xyz, outResult.vpos.xyz, worldToTangent);       
    #endif
        
    #ifdef _LIGHT1_POINT
        outResult.lightDir1.xyz = GetPointLightDirectionInTangentSpace(g_lightPosition1.xyz, outResult.vpos.xyz, worldToTangent);               
    #endif
    
    #ifdef _LIGHT2_POINT
        outResult.lightDir2.xyz = GetPointLightDirectionInTangentSpace(g_lightPosition2.xyz, outResult.vpos.xyz, worldToTangent);               
    #endif
    
    #ifdef _LIGHT3_POINT
        outResult.lightDir3.xyz = GetPointLightDirectionInTangentSpace(g_lightPosition3.xyz, outResult.vpos.xyz, worldToTangent);                       
    #endif
    
    /// Calculate the view space normal, vertex position and viewer position
    /// This are going to be used to calculate the vertex uv
    /// Create parameters for autogenerated coordinates
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION)  || defined(_UV1_AUTO_SPHERE)  || defined(_UV1_AUTO_SPHEREVIEW) 
        float3 P        = outResult.vpos.xyz;                                   ///< Vertex position in world space
        float3  N       = Transform((float3x3) g_matWorld, normal);         ///< Normal in world space
        float3  V       = normalize(P-g_cameraPos.xyz);             ///< Viewer position
        N               = normalize(N);
    #endif
    
    /// Calculate the uv transformations for the diffuse layer
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW)
        outResult.uvcoords.xy = GetUVCoordinate3L0(P, N, V);        
    #elif defined(_HAS_UV0)
        outResult.uvcoords.xy = inVertex.uv0;       
    #endif
    
    float3 env = 0;
    #ifndef _MAP_PLANAR_REFLECTION
        #if defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION) || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
            #ifdef _MAP_ENVIROMENT_CUBE
                env = GetUVCoordinate3L1(P, N, V);
            #else
                env.xy = GetUVCoordinate3L1(P, N, V);
            #endif
        #elif defined(_HAS_UV0)
            env.xy  = inVertex.uv0;
            env.z   = 1;
        #endif
    #endif
        
    /// Finally transform the uv coordinates by the texture matrix transformations
    float3 uv3;
    uv3.xy = outResult.uvcoords.xy;
    uv3.z = 1;

    outResult.uvcoords.xy = outResult.uvcoords.xy * g_textureTransform0.xy + outResult.uvcoords.yx * g_textureTransformExt0.yx + g_textureTransform0.zw;

    #ifndef _MAP_ENVIROMENT_CUBE
        env.xy = env.xy * g_textureTransform1.xy + env.yx * g_textureTransformExt1.yx + g_textureTransform1.zw;
    #endif
    
    #if !defined(_MAP_PLANAR_REFLECTION)
        outResult.uvcoords.zw = env.xy;
        outResult.vpos.w = env.z;
    #else
        float4 ScreenSpace = TransformPlanarReflection(outResult.hpos);
        outResult.uvcoords.zw = ScreenSpace.xy;
        outResult.vpos.w = ScreenSpace.z;
    #endif
    
    /// Write the UV used for the lightmap
    #ifdef _HAS_UV1
        outResult.lightDir0.w = inVertex.uv1.x; 
        outResult.lightDir1.w = inVertex.uv1.y; 
    #elif defined(_HAS_UV0)
        outResult.lightDir0.w = inVertex.uv0.x; 
        outResult.lightDir1.w = inVertex.uv0.y; 
    #endif

    /// Write the view direction in tangent space   
    //< Vertex position in world space
//#if !defined(_MATERIAL_NOSPECULAR) || defined(_PARALLAX)
    outResult.viewDir.xyz   = g_cameraPos.xyz - outResult.vpos.xyz;
    outResult.viewDir.xyz   = mul(worldToTangent, outResult.viewDir.xyz);
    outResult.viewDir.xyz = normalize(outResult.viewDir.xyz);
//#endif
}

///////////////////////////////////////////////
// Spot Per Pixel Vertex Shader
///////////////////////////////////////////////
void MultilayerPPLSpot_MainVS( Multilayer_InputVS inVertex,out MultilayerPPLSpot_OutputVS outResult)
{
    outResult = (MultilayerPPLSpot_OutputVS) 0;
    float3 tempNormal = float3(0,0,1);
    float3 tempTangent = float3(1,0,0);
    outResult.color = float4(1,1,1,1);

    #ifdef _HAS_NORMAL
        tempNormal = normalize(inVertex.normal);
    #endif
    
    #if defined(_HAS_TANGENT3) || defined(_HAS_TANGENT)
        tempTangent = normalize(inVertex.tangent);
    #endif

    #ifdef _HAS_COLOR
        outResult.color = inVertex.color;
    #endif

#ifdef _USE_SKINMATRIX  
    SKINVERTEX v = SkinVertex(inVertex.pos.xyz, tempNormal, tempTangent, inVertex.indices, inVertex.weight);
    float4 position = v.P;
    float3 normal   = v.N;
    float3 tangent  = v.T;  
#else
    float4 position = float4(inVertex.pos.xyz,1);
    float3 normal   = normalize(tempNormal); 
    float3 tangent  = normalize(tempTangent);
#endif

    /// Transform the position and the normal to projection space
    outResult.vpos  = Transform(g_matWorld, position);
#if defined (_USE_TAPER)
    outResult.vpos  = TaperVert(outResult.vpos.xyz);
    outResult.hpos    = Transform(g_matViewProjection, float4(outResult.vpos.xyz,1));
#else
    outResult.hpos  = Transform(g_matWorldViewProjection, position);
#endif

#ifdef _PS3_VSCLIPPLANE0
    outResult.oClip0    = dot(outResult.vpos, g_ps3ClipPlane0);
#endif
    
    /// Compute the tangent transformation matrix
    float3x3 worldToTangent = GetWorldToTangentMatrix((float3x3)g_matWorld, tangent,normal);    

#ifdef _HAS_TANGENT
    worldToTangent[1] *= inVertex.tangent.w;
#endif
    
    
    /// Determinate the view vector
#if !defined(_MATERIAL_NOSPECULAR) && defined(_PARALLAX)
    float3  view = g_cameraPos.xyz - outResult.vpos.xyz;
    outResult.view.xyz = Transform(worldToTangent, view);
    outResult.view.xyz = normalize(outResult.view.xyz);
#endif      
        
    /// Calculate the view space normal, vertex position and viewer position
    /// This are going to be used to calculate the vertex uv
    
    /// Create parameters for autogenerated coordinates
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION)  || defined(_UV0_AUTO_SPHERE)  || defined(_UV0_AUTO_SPHEREVIEW) 
        float3 P        = outResult.vpos.xyz;                                   ///< Vertex position in world space
        float3  N       = Transform((float3x3) g_matWorld, normal);         ///< Normal in world space
        float3  V       = -normalize(P-g_cameraPos);                ///< Viewer position
        N               = normalize(N);
    #endif
        
    /// Calculate the uv transformations for the diffuse layer
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW)
        outResult.uv0 = GetUVCoordinate3L0(P, N, V);        
    #elif defined(_HAS_UV0)     
        outResult.uv0.xy    = inVertex.uv0;
        outResult.uv0.z = 1;
    #endif
    
    
    /// Finally transform the uv coordinates by the texture matrix transformations
    outResult.uv0.xy = outResult.uv0.xy * g_textureTransform0.xy + outResult.uv0.yx * g_textureTransformExt0.yx + g_textureTransform0.zw;
    
        
    /// Calculate spot light lightining attributes
    float   factor;
    float   fNDotLSpot;
    #ifdef _LIGHT0_SPOT
        OutLightDirSpotPPL(g_lightPosition0.xyz - outResult.vpos.xyz, g_lightPosition0.w, worldToTangent, outResult.lightDir0.xyz, outResult.lightDir0.w);
        
        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, position);
        #endif

        outResult.spotProjection1 = Transform(g_matTexture2, position);
    #endif
    
    #ifdef _LIGHT1_SPOT
        OutLightDirSpotPPL(g_lightPosition1.xyz - outResult.vpos.xyz, g_lightPosition1.w, worldToTangent, outResult.lightDir1.xyz, outResult.lightDir1.w);
        outResult.spotProjection2 = Transform(g_matTexture3, position);
    #endif
}




///////////////////////////////////////////////
// Omni & Direct Vertex Shader
///////////////////////////////////////////////
void MultilayerPVL_MainVS( Multilayer_InputVS inVertex,out  MultilayerPVL_OuputVS outResult)
{
    outResult = (MultilayerPVL_OuputVS) 0;
#ifndef _POINTSPRITE    
    outResult.normal = float3(0,0,1);
    outResult.color = float4(1,1,1,1);
    
    #ifdef _HAS_NORMAL
        outResult.normal = normalize(inVertex.normal);
    #endif
    
    #ifdef _HAS_COLOR
        outResult.color = inVertex.color;
    #endif
        
#ifdef _USE_SKINMATRIX  
    SKINVERTEX v = SkinVertex(inVertex.pos.xyz, outResult.normal, float3(1,0,0), inVertex.indices, inVertex.weight);
    float4 position = v.P;
    float3 normal   = v.N;
#else
    float4 position = float4(inVertex.pos.xyz,1);
    float3 normal   = outResult.normal; 
#endif

    /// Transform the position to clip space
    outResult.vpos  = Transform(g_matWorld, position);
#if defined (_USE_TAPER)
    outResult.vpos  = float4(TaperVert(outResult.vpos.xyz),1);
    outResult.hpos    = Transform(g_matViewProjection, outResult.vpos);
#else
    outResult.hpos  = Transform(g_matWorldViewProjection, position);
#endif
    outResult.normal    = Transform ((float3x3) g_matWorld, normal);            ///< Normal in world space
#ifdef _PS3_VSCLIPPLANE0
    outResult.oClip0    = dot(outResult.vpos, g_ps3ClipPlane0);
#endif
    
    /// Create parameters for autogenerated coordinates
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION)  || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
        float3 P        = outResult.vpos.xyz;                                   ///< Vertex position in world space
        float3  N       = Transform((float3x3) g_matWorld, normal); ///< Normal in world space
        float3  V       = normalize(P-g_cameraPos);             ///< Viewer position
        N               = normalize(N);
    #endif
    
    /// Calculate the uv transformations for the diffuse layer
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW)
        outResult.uv0.xy = GetUVCoordinate3L0(P, N, V);     
    #elif defined(_HAS_UV0)     
        outResult.uv0.xy    = inVertex.uv0;
        outResult.uv0.z = 1;
    #endif
    
    float3 env = 0;
    /// Calculate the uv transformation for the enviromental layer
    #if defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION) || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
        #ifdef _MAP_ENVIROMENT_CUBE
            env = GetUVCoordinate3L1(P, N, V);
        #else
            env.xy = GetUVCoordinate3L1(P, N, V);
        #endif
        
        #if defined(_MAP_PLANAR_REFLECTION) || defined(_MAP_ENVIROMENT)
            outResult.uv1 = env;
        #endif
    #elif defined(_HAS_UV0)
        #if defined(_MAP_PLANAR_REFLECTION) || defined(_MAP_ENVIROMENT)
            outResult.uv1.xy    = inVertex.uv0;
            outResult.uv1.z = 1;        
        #endif
    #endif

    /// Finally transform the uv coordinates by the texture matrix transformations
    outResult.uv0.xy = outResult.uv0.xy * g_textureTransform0.xy + outResult.uv0.yx * g_textureTransformExt0.yx + g_textureTransform0.zw;

    #ifndef _MAP_ENVIROMENT_CUBE
        #if defined(_MAP_PLANAR_REFLECTION) || defined(_MAP_ENVIROMENT)
            outResult.uv1.xy = outResult.uv1.xy * g_textureTransform1.xy + outResult.uv1.yx * g_textureTransformExt1.yx + g_textureTransform1.zw;
        #endif
    #endif
    
    /// Write the UV used for the lightmap
    #ifdef _HAS_UV1
        outResult.uv2 = inVertex.uv1;
    #elif defined(_HAS_UV0)
        outResult.uv2 = inVertex.uv0;
    #endif
    
    
    /// The outResult.view vector is only used to calculate specular lighting, so if there is no specular
    /// dont calculate the view
    #ifndef _MATERIAL_NOSPECULAR
        float3 pWorld   = Transform(g_matWorld, position);                  ///< Vertex position in world space
        outResult.view      = normalize(g_cameraPos - pWorld);              ///< View direction
    #endif
    
    #ifdef _MAP_PLANAR_REFLECTION
        float4 ScreenSpace = TransformPlanarReflection(outResult.hpos);
        outResult.uv1.xyz = ScreenSpace.xyz;
    #endif
        
    #ifdef _LIGHT0_DIRECTIONAL
        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, position);
        #endif
    #endif

    /// Calculate lighting for point lights
    /*
    float3 lightDir;
    #ifdef _LIGHT0_POINT
        OutLightDirPointPVL(g_lightPosition0.xyz - outResult.vpos, g_lightPosition0.w, lightDir, outResult.lightfactors.x);
    #endif
    
    #ifdef _LIGHT1_POINT
        OutLightDirPointPVL(g_lightPosition1.xyz - outResult.vpos, g_lightPosition1.w, lightDir, outResult.lightfactors.y);
    #endif
    
    #ifdef _LIGHT2_POINT
        OutLightDirPointPVL(g_lightPosition2.xyz - outResult.vpos, g_lightPosition2.w, lightDir, outResult.lightfactors.z);
    #endif
    
    #ifdef _LIGHT3_POINT
        OutLightDirPointPVL(g_lightPosition3.xyz - outResult.vpos, g_lightPosition3.w, lightDir, outResult.lightfactors.w);
    #endif
    */
    
#else//POINTSPRITE
    outResult.color     = inVertex.color;
    outResult.hpos      = Transform( g_matWorldViewProjection, inVertex.pos);
    float d         = distance(inVertex.pos.xyz, g_cameraPos.xyz);
    
    outResult.pointSize = inVertex.uv0.x / d;
    outResult.pointSize *= g_screenSize.x;
#endif  
}

///////////////////////////////////////////////
// Spot Vertex Shader
///////////////////////////////////////////////
void MultilayerPVLSpot_MainVS( Multilayer_InputVS inVertex,out MultilayerPVLSpot_OuputVS outResult)
{
    outResult = (MultilayerPVLSpot_OuputVS) 0;
    outResult.normal = float3(0,0,1);
    outResult.color = float4(1,1,1,1);
    
    #ifdef _HAS_NORMAL
        outResult.normal = normalize(inVertex.normal);
    #endif
    
    #ifdef _HAS_COLOR
        outResult.color = inVertex.color;
    #endif
        
#ifdef _USE_SKINMATRIX  
    SKINVERTEX v = SkinVertex(inVertex.pos.xyz, outResult.normal, float3(1,0,0), inVertex.indices, inVertex.weight);
    float4 position = v.P;
    float3 normal   = v.N;
#else
    float4 position = float4(inVertex.pos.xyz,1);
    float3 normal   = outResult.normal; 
#endif

    /// Transform the position to clip space
    outResult.vpos  = Transform(g_matWorld, position);
#if defined (_USE_TAPER)
    outResult.vpos  = TaperVert(outResult.vpos.xyz);
    outResult.hpos    = Transform(g_matViewProjection, float4(outResult.vpos.xyz,1));
#else
    outResult.hpos  = Transform(g_matWorldViewProjection, position);
#endif
    outResult.normal    = Transform ((float3x3) g_matWorld, normal);            ///< Normal in world space
    
#ifdef _PS3_VSCLIPPLANE0
    outResult.oClip0    = dot(outResult.vpos, g_ps3ClipPlane0);
#endif
    
    /// Create parameters for autogenerated coordinates
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW) || defined(_UV1_AUTO_POSITION) || defined(_UV1_AUTO_NORMAL) || defined(_UV1_AUTO_REFLECTION)  || defined(_UV1_AUTO_SPHERE) || defined(_UV1_AUTO_SPHEREVIEW)
        float3 P        = outResult.vpos.xyz;                                   ///< Vertex position in world space
        float3  N       = Transform((float3x3) g_matWorld, normal);         ///< Normal in world space
        float3  V       = -normalize(P-g_cameraPos);                ///< Viewer position
        N               = normalize(N);
    #endif
    
    /// Calculate the uv transformations for the diffuse layer
    #if defined(_UV0_AUTO_POSITION) || defined(_UV0_AUTO_NORMAL) || defined(_UV0_AUTO_REFLECTION) || defined(_UV0_AUTO_SPHERE) || defined(_UV0_AUTO_SPHEREVIEW)
        outResult.uv0 = GetUVCoordinate3L0(P, N, V);        
    #elif defined(_HAS_UV0)     
        outResult.uv0.xy    = inVertex.uv0;
        outResult.uv0.z = 1;
    #endif
    
    /// Finally transform the uv coordinates by the texture matrix transformations
    outResult.uv0.xy = outResult.uv0.xy * g_textureTransform0.xy + outResult.uv0.yx * g_textureTransformExt0.yx + g_textureTransform0.zw;

    /// Calculate spot light lightining attributes
    float   factor;
    float   fNDotLSpot;
    #ifdef _LIGHT0_SPOT
        outResult.spotProjection1 = Transform(g_matTexture2, position);

        OutLightDirSpotPVL(g_lightPosition0.xyz - outResult.vpos.xyz, g_lightPosition0.w, outResult.lightDir0.xyz, outResult.lightDir0.w);

        #ifdef __USE_SHADOWMAP
            outResult.shadowProjection = Transform(g_matTextureProjection, position);
        #endif
    #endif
    
    #ifdef _LIGHT1_SPOT
        outResult.spotProjection2 = Transform(g_matTexture3, position);
    
        OutLightDirSpotPVL(g_lightPosition1.xyz - outResult.vpos.xyz, g_lightPosition1.w, outResult.lightDir1.xyz, outResult.lightDir1.w);
    #endif
    
    /// The outResult.view vector is only used to calculate specular lighting, so if there is no specular
    /// dont calculate the view
    #ifndef _MATERIAL_NOSPECULAR
        float3 pWorld   = Transform(g_matWorld, position);                  ///< Vertex position in world space
        outResult.view      = g_cameraPos.xyz - pWorld;                         ///< View direction
    #endif
}

#endif

///////////////////////////////////////////////////////////////
//PIXEL SHADERS
///////////////////////////////////////////////////////////////
#if defined(_PIXEL_SHADER)



#ifdef _PERPIXEL_LIGHTING
    #ifdef _LIGHT0_SPOT
        #define MULTILAYER_OUTPUT_PS        MultilayerPVL_OutputPS
        #define MULTILAYER_INPUT_PS         MultilayerPPLSpot_OutputVS
        #define MULTILAYER_MAIN_PS          MultilayerPPLSpot_MainPS
    #else
        #define MULTILAYER_OUTPUT_PS        MultilayerPVL_OutputPS
        #define MULTILAYER_INPUT_PS         MultilayerPPL_OutputVS
        #define MULTILAYER_MAIN_PS          MultilayerPPL_MainPS
    #endif
#else
    #ifdef _LIGHT0_SPOT
        #define MULTILAYER_OUTPUT_PS        MultilayerPVL_OutputPS
        #define MULTILAYER_INPUT_PS         MultilayerPVLSpot_OuputVS
        #define MULTILAYER_MAIN_PS          MultilayerPVLSpot_MainPS
    #else
        #define MULTILAYER_OUTPUT_PS        MultilayerPVL_OutputPS
        #define MULTILAYER_INPUT_PS         MultilayerPVL_OuputVS
        #define MULTILAYER_MAIN_PS          MultilayerPVL_MainPS
    #endif
#endif

void MultilayerPPL_MainPS(MultilayerPPL_OutputVS inData         ,   out MultilayerPVL_OutputPS outResult);
void MultilayerPPLSpot_MainPS(MultilayerPPLSpot_OutputVS inData,    out MultilayerPVL_OutputPS outResult);
void MultilayerPVL_MainPS(MultilayerPVL_OuputVS inData          ,   out MultilayerPVL_OutputPS outResult);
void MultilayerPVLSpot_MainPS(MultilayerPVLSpot_OuputVS inData  ,   out MultilayerPVL_OutputPS outResult);

uniform sampler2D g_diffuseMap          : register(s0);
#ifdef _MAP_ENVIROMENT_CUBE
    uniform samplerCUBE g_enviromentMap : register(s1);
#else
    uniform sampler2D   g_enviromentMap : register(s1);
#endif
uniform sampler2D g_glossMap            : register(s2);
uniform sampler2D g_lightMap            : register(s3);
uniform sampler2D g_specularMap         : register(s4);
uniform sampler2D g_emissiveMap         : register(s5);
uniform sampler2D g_normalMap           : register(s6);
uniform sampler2D g_planarReflection    : register(s7);
uniform sampler2D g_spot1Map            : register(s8);
uniform sampler2D g_spot2Map            : register(s9);
uniform sampler2D g_diffuse2Map         : register(s10);

/// Tongas upload variables
#ifdef _VERTICAL_FOG
    float4      g_verticalFogColor;
    float4      g_verticalFogValues;
#endif

#ifdef _PIXEL_FOG
    float4      g_pixelFogColor;
    float4      g_pixelFogOptions;
#endif

#ifdef _PARALLAX
    float       g_fParallaxScale;
#endif

#if defined(_CAMERA_LIGHT) || defined(_RIM_FADING)
    float4      g_cameraDir;
    float4      g_cameraLightColor;
#endif

float4 g_lightMapColor;

#if defined(_MRT)
#define _MRT_DEFAULT_COLOR      float4(0,0,0,0)
#define _MRT_BLACK_COLOR        float4(0,0,0,1)

#ifndef _PIXEL_FOG
    float4      g_pixelFogOptions;
#endif

uniform float4      g_multilayerTextureOptions;

float4 getBloomOutput(float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;

    #if !defined(_POINTSPRITE)
    float4  ret = float4(0,0,0,1);
    ret.g = g_emissiveColor.a;
    #else
    float4  ret = float4(0,1,0,1);
    #endif

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }
    
    ret*=mulFactor;

    return ret;
}

#if !defined(_POINTSPRITE)
float4 getFocusBloomOutput(float opacity,float3 pos,float2 uvCoords,uniform sampler2D tex)
{
    float mulFactor = 0;

    if(g_emissiveColor.a>0)
        mulFactor = 1;
    if(opacity>=1)
        mulFactor = 1;

    float4  ret = float4(0,0,0,opacity);
    ret.g = g_emissiveColor.a*opacity;

    // Determinate the alpha color from the diffuse stage
    if (g_multilayerTextureOptions.x > 1)
    {
        /// Texture with additive blending
        float4 color = tex2D( tex, uvCoords );
        ret.a*= (color.r + color.g + color.b)*0.3333 * color.a;
    }   
    else if (g_multilayerTextureOptions.x > 0)
    {
        // Texture with alpha
        ret.a*= tex2D( tex, uvCoords ).a;
    }

    ret*=mulFactor;
    return ret;
}
#endif

#if defined(_MULTILAYER_CGFX)

//default output
float4 pso_MRT_default_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_default_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(MultilayerPPLSpot_OutputVS IN,float4 mainColor)
{
    #if !defined(_POINTSPRITE)
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
    #else
    return getBloomOutput(IN.uv.xy,g_diffuseMap);
    #endif
}

float4 pso_MRT_focusBloom_output(MultilayerPPL_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uvcoords.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVLSpot_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

float4 pso_MRT_focusBloom_output(MultilayerPVL_OuputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_diffuseMap);
}

#endif

//default output
#if defined(_COMPOSITE_CGFX)
#ifndef _POINTSPRITE
float4 pso_MRT_default_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(Composite_OutputVS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(Composite_OutputVS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(Composite_OutputVS IN,float4 mainColor)
{
    return getFocusBloomOutput(mainColor.a,IN.vpos.xyz,IN.uv0.xy,g_layer0);
}

#else
float4 pso_MRT_default_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_DEFAULT_COLOR;
}

float4 pso_MRT_black_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return _MRT_BLACK_COLOR;
}

float4 pso_MRT_blackBoolAlpha_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return float4(_MRT_BLACK_COLOR.rgb,(mainColor.a>=1.0)?1.0:0.0);
}

float4 pso_MRT_focusBloom_output(CompositeSprite_InputPS IN,float4 mainColor)
{
    return getBloomOutput(IN.uv.xy,g_layer0);
}
#endif
#endif

#if defined(_MRT3) && !defined(_MRT2)
#define _MRT2
#endif

#if defined(_MRT2) && !defined(_MRT1)
#define _MRT1
#endif

#if defined(_MRT1) && !defined(_MRT1_OUTMETHOD)
    #define _MRT1_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT2) && !defined(_MRT2_OUTMETHOD)
    #define _MRT2_OUTMETHOD     pso_MRT_default_output
#endif

#if defined(_MRT3) && !defined(_MRT3_OUTMETHOD)
    #define _MRT3_OUTMETHOD     pso_MRT_default_output
#endif
#endif

#if defined(_ALPHA_TEST)
float4      g_PixelAlphaTesting;
#endif

void main_PS(   MULTILAYER_INPUT_PS inData,out MULTILAYER_OUTPUT_PS outResult)
{
    MULTILAYER_MAIN_PS(inData,outResult);
    
    #if defined(_MRT1)
        outResult.color1 = _MRT1_OUTMETHOD(inData,outResult.color);
    #endif

    #if defined(_MRT2)
        outResult.color2 = _MRT2_OUTMETHOD(inData,outResult.color);
    #endif

    #if defined(_MRT3)
        outResult.color3 = _MRT3_OUTMETHOD(inData,outResult.color);
    #endif
    
    #if defined(_ALPHA_TEST)
        clip(outResult.color.a-g_PixelAlphaTesting.x);
    #endif
}

///////////////////////////////////////////////
// Omni & Direct Per Pixel PixelShader
///////////////////////////////////////////////
void MultilayerPPL_MainPS( MultilayerPPL_OutputVS inData,out MultilayerPVL_OutputPS outResult)
{
    outResult = (MultilayerPVL_OutputPS) 0;

    float3  view = normalize(inData.viewDir.xyz);
    
    #ifdef _PARALLAX
        inData.uvcoords.xy += (tex2D(g_normalMap, inData.uvcoords.xy).a * g_fParallaxScale - g_fParallaxScale*.5f ) * view;
    #endif
    
    // As the usage of the second diffuse is encoded on the lightmap, must retrieve that first
    #if defined (_MAP_LIGHTMAP) || defined (BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA)
        float4 lightMapColor;
        float2 luv;
        luv.x = inData.lightDir0.w;
        luv.y = inData.lightDir1.w;
        lightMapColor = tex2D( g_lightMap, luv);
        lightMapColor.rgb *= g_lightMapColor.rgb;
        lightMapColor.rgb *= g_lightMapColor.a;
    #endif // _MAP_LIGHTMAP
    
    // Calculate the albedo color
    // Start with the vertex color, separate color from alpha for best processing
    // BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA means that we merge to diffuse textures with the lighmap alpha color
    float3 albedo   = inData.color.rgb;
    float opacity   = inData.color.a;
    
    #ifdef _MAP_DIFFUSE
        #ifdef BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA
            // Merge both diffuse maps with the alpha color of the lightmap
            float4 albedoTexture = lerp(    tex2D( g_diffuseMap, inData.uvcoords.xy ), 
                                            tex2D( g_diffuse2Map, inData.uvcoords.xy ), 
                                            lightMapColor.a);
        #else
            float4 albedoTexture = tex2D( g_diffuseMap, inData.uvcoords.xy );
        #endif
        
        albedo*=albedoTexture.rgb;
                
        #if !defined(_ALPHACAMERALIGHTMASK) && !defined(_TRANSLUCENCY) && !defined(_ALPHAENVIROMENTMASK)
            opacity*=albedoTexture.a;
        #endif
    #endif
    
    /// Retrieve the normal for the model, this is in normal texture space
    float3 normal =  normalize( 2.0 * tex2D( g_normalMap, inData.uvcoords.xy ).rgb - 1.0 ); 

    /// Calculate lighting  -----------------------------------------------------------------------
        
    // If we have a light with a shadowmap, lets retrieve it early for different objectives
    #ifdef __USE_SHADOWMAP
        #if defined (_LIGHT0_DIRECTIONAL)
            float shadow = GetShadowDirectional(inData.shadowProjection);       
        #elif defined ( _LIGHT0_POINT )
            float shadow = GetShadowPoint(inData.vpos.xyz);
        #endif
    #endif
    
    // Check for static lighting conditions (lightmap)
    // In the case of not having lightmaps, start with black
    #ifdef _MAP_LIGHTMAP
        outResult.color.rgb = 2.0f * albedo * lightMapColor.rgb;
        
        // Check if we must apply the shadow on the lightmap
        #ifdef _SHADOWLIGHTMAP
            outResult.color.rgb*=shadow;
        #endif
    #else
        outResult.color.rgb = 0;
    #endif
    
    /// Now proceed with dynamic lighting   
    float   fNDotL;                 ///< Auxiliary to calculate how does the light affects the surface
    float3  fvLightDir;             ///< Auxiliary for the light direction
    float3  myLight     = 0;        ///< This will acumulate the diffuse lighting   
    float3  mySpecular  = 0;        ///< This will acumulate the specular lighting

    /// Calculate directional lighting      
    #if defined (_LIGHT0_DIRECTIONAL) && !defined(_ONLYSHADOW)
            LightDirectional_PPL_PS(inData.lightDir0.xyz, normal, view, g_lightColor0.xyz, g_lightSpecular0.xyz, myLight, mySpecular);
        #ifdef __USE_SHADOWMAP          
            myLight *= shadow;
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
    #endif
    
    #ifdef _LIGHT1_DIRECTIONAL      
        LightDirectional_PPL_PS(inData.lightDir1.xyz, normal, view, g_lightColor1.xyz, g_lightSpecular1.xyz, myLight, mySpecular);      
    #endif
    
    #ifdef _LIGHT2_DIRECTIONAL      
        LightDirectional_PPL_PS(inData.lightDir2.xyz, normal, view, g_lightColor2.xyz, g_lightSpecular2.xyz, myLight, mySpecular);
        
    #endif
    
    #ifdef _LIGHT3_DIRECTIONAL      
        LightDirectional_PPL_PS(inData.lightDir3.xyz, normal, view, g_lightColor3.xyz, g_lightSpecular3.xyz, myLight, mySpecular);      
    #endif
    
    
    #define myAmbientLight g_ambient.rgb
        
    /// Calculate point lights
    #if defined (_LIGHT0_POINT) && !defined(_ONLYSHADOW)    
        AddPointLightContributionTangentSpace(inData.lightDir0.xyz, g_lightPosition0.xyz, g_lightPosition0.w, g_lightColor0.rgb, g_lightSpecular0.rgb, 
                                                normal, view, inData.vpos, myLight, mySpecular);
        #ifdef __USE_SHADOWMAP      
            myLight *= shadow;
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
    #endif  
    
    #ifdef _LIGHT1_POINT
        AddPointLightContributionTangentSpace(inData.lightDir1.xyz, g_lightPosition1.xyz, g_lightPosition1.w, g_lightColor1.rgb, g_lightSpecular1.rgb, 
                                                normal, view, inData.vpos, myLight, mySpecular);
    #endif  
    
    #ifdef _LIGHT2_POINT
        AddPointLightContributionTangentSpace(inData.lightDir2.xyz, g_lightPosition2.xyz, g_lightPosition2.w, g_lightColor2.rgb, g_lightSpecular2.rgb, 
                                                normal, view, inData.vpos, myLight, mySpecular);
    #endif  
    
    #ifdef _LIGHT3_POINT
        AddPointLightContributionTangentSpace(inData.lightDir3.xyz, g_lightPosition3.xyz, g_lightPosition3.w, g_lightColor3.rgb, g_lightSpecular3.rgb, 
                                                normal, view, inData.vpos, myLight, mySpecular);
    #endif  
    
    #ifdef _NON_LIGHTED
        myLight = 1;
    #endif

    /// Apply the directional lighting to the output color
    outResult.color.rgb += albedo * (myLight * g_diffuseColor.rgb + myAmbientLight * g_ambientColor.rgb);

    /// If we got a specular map then proceed to get the specular color from it         
    #ifndef _MATERIAL_NOSPECULAR
        float3 mySpecularColor = g_specularColor.rgb;
        #ifdef _MAP_SPECULAR
            mySpecularColor *= tex2D(g_specularMap,inData.uvcoords.xy ).rgb;
        #endif
        outResult.color.rgb += mySpecular * mySpecularColor;
    #endif
                
    /// Apply the enviromental using the gloss map
    #ifdef _MAP_PLANAR_REFLECTION
        float2 refCoords = inData.uvcoords.zw/inData.vpos.w;
        
        #ifdef _PARALLAX
            refCoords += normal * g_fParallaxScale;
        #else
            refCoords += normal * .01f;
        #endif

        float3 reflection = tex2D(g_planarReflection, refCoords);

        #ifdef _MAP_ENVIROMENTGLOSS
            reflection *= tex2D( g_glossMap, inData.uvcoords.xy );
        #endif
        
        outResult.color.rgb += reflection;
    #else
        #ifdef _MAP_ENVIROMENT
            #ifdef _MAP_ENVIROMENT_CUBE
                float3 enviroment = texCUBE( g_enviromentMap, float3(inData.uvcoords.zw, inData.vpos.w) ).rgb;
            #else
                float3 enviroment = tex2D( g_enviromentMap, inData.uvcoords.zw ).rgb;
            #endif
            
            #ifdef _MAP_ENVIROMENTGLOSS
                enviroment.rgb *= tex2D( g_glossMap, inData.uvcoords.xy ).rgb;
            #endif
            
            outResult.color.rgb += enviroment.rgb * g_enviromentColor.rgb;
        #endif
    #endif
        
    
    
    /// Apply emissive material color and map
    /// Then saturate the color
    outResult.color.rgb += g_emissiveColor.rgb;
    #ifdef _MAP_EMISSIVE
        #ifdef _EMISSIVE_FLIPBOOK
            inData.uvcoords.z = 1;
            float2 euv = inData.uvcoords.xy * g_textureTransform5.xy + g_textureTransform5.zw;
            outResult.color.rgb+= tex2D( g_emissiveMap, euv).rgb;
        #else
            outResult.color.rgb+= tex2D( g_emissiveMap, inData.uvcoords.xy).rgb;
        #endif
    #endif
    
    float fogValue;
    #ifdef _VERTICAL_FOG
        fogValue = saturate( (inData.vpos.y - g_verticalFogValues.x) / g_verticalFogValues.z);
        outResult.color.rgb =   lerp(g_verticalFogColor.rgb, outResult.color.rgb, fogValue);
    #endif

    #ifdef _PIXEL_FOG
        ComputeFog(outResult.color,g_pixelFogColor.rgb,distance(g_cameraPos.xyz, inData.vpos.xyz),g_pixelFogOptions.x,g_pixelFogOptions.z);
    #endif
    
    // Calculate the output alpha from the calculated opacity and from the material diffuse color
    outResult.color.a = opacity * g_diffuseColor.a;

    #ifdef _CAMERA_LIGHT
        float vdn = abs(dot(view,normal));
        vdn = saturate(vdn);
        vdn = 1 - vdn;
        vdn *= vdn;
        #ifdef _ALPHACAMERALIGHTMASK
         vdn*=albedoTexture.a;
        #endif
        outResult.color.rgb += vdn * g_cameraLightColor.rgb;
    #endif

    #if defined(_RIM_FADING)
        outResult.color.a*=GetRimFading(g_cameraPos.xyz,inData.vpos.xyz,normal,g_RimFading.y);
    #endif
}

///////////////////////////////////////////////
// Spot Per Pixel PixelShader
///////////////////////////////////////////////
void MultilayerPPLSpot_MainPS( MultilayerPPLSpot_OutputVS inData,out MultilayerPVL_OutputPS outResult)
{   
    outResult = (MultilayerPVL_OutputPS)1;

    #ifdef _PARALLAX
        inData.uv0.xy += (tex2D(g_normalMap, inData.uv0.xy).a * g_fParallaxScale - g_fParallaxScale*.5f ) * normalize(inData.view);
    #endif
    
    float4 diffuseColor = tex2D( g_diffuseMap, inData.uv0.xy );
    
    /// Retrieve the normal for the model, this is in normal texture space
    float3 normal =  normalize( 2.0 * tex2D( g_normalMap, inData.uv0.xy ).rgb - 1.0 );  

    /// Calculate lighting      
    float   fNDotL;
    float   fNDotLSpot;
    float3  myLight     = 0;
    float3  fvLightDir;
    float4  lightColor;
    float   factor;
    float3  mySpecular  = 0;
    float3  Half;
    float3  view = 0;
    
    #if !defined(_MATERIAL_NOSPECULAR)
        view = normalize(inData.view.xyz);
    #endif
    
    #ifdef _LIGHT0_SPOT
        fvLightDir = g_lightPosition0.xyz - inData.vpos;
        LightSpot_PPL_PS(inData.lightDir0.xyz, normal, view, (dot(normalize(fvLightDir),-g_lightDirection0.xyz)>0) * inData.lightDir0.w, g_lightColor0, g_lightSpecular0, myLight, mySpecular, g_spot1Map, inData.spotProjection1);
        #ifdef __USE_SHADOWMAP
            float shadow = GetShadowSpot(inData.shadowProjection);
            myLight *= shadow;  
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
    #endif  
    
    #ifdef _LIGHT1_SPOT     
        fvLightDir = g_lightPosition1.xyz - inData.vpos;
        LightSpot_PPL_PS(inData.lightDir1.xyz, normal, view, (dot(normalize(fvLightDir),-g_lightDirection1.xyz)>0) * inData.lightDir1.w, g_lightColor1, g_lightSpecular1, myLight, mySpecular, g_spot2Map, inData.spotProjection2);
    #endif
        
    outResult.color.rgb = myLight * saturate(diffuseColor.rgb) * g_diffuseColor.rgb;

    #ifndef _MATERIAL_NOSPECULAR
        float3 mySpecularColor = g_specularColor.rgb;
        #ifdef _MAP_SPECULAR
            mySpecular *= tex2D(g_specularMap,inData.uv0.xy ).rgb;
        #endif
        outResult.color.rgb += mySpecular * mySpecularColor;
    #endif
    
    /// Apply alpha from the material diffuse color
    outResult.color.a = inData.color.a * g_diffuseColor.a * diffuseColor.a;

    #if defined(_RIM_FADING)
        outResult.color.a*=GetRimFading(g_cameraPos.xyz,inData.vpos.xyz,normal,g_RimFading.y);
    #endif
}

///////////////////////////////////////////////
// Omni & Direct Per Vertex PixelShader
///////////////////////////////////////////////
void MultilayerPVL_MainPS( MultilayerPVL_OuputVS inData,out MultilayerPVL_OutputPS outResult)
{
    outResult = (MultilayerPVL_OutputPS) 0;

    /// Determinate the surface diffuse color
    outResult.color = inData.color;
    
#ifndef _POINTSPRITE
    // Retrieve the albedo texture
    
    // As the usage of the second diffuse is encoded on the lightmap, must retrieve that first
    #if defined (_MAP_LIGHTMAP) || defined (BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA)
        float4 lightMapColor;
        lightMapColor = tex2D( g_lightMap, inData.uv2); 
        lightMapColor.rgb *= g_lightMapColor.rgb;   
        lightMapColor.rgb *= g_lightMapColor.a; 
    #endif // _MAP_LIGHTMAP
    
    // Calculate the albedo color
    // Start with the vertex color, separate color from alpha for best processing
    // BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA means that we merge to diffuse textures with the lighmap alpha color
    float3 albedo   = inData.color.rgb;
    float opacity   = inData.color.a;
    
    #ifdef _MAP_DIFFUSE
        #if defined(BLEND_DIFFUSE2_WITH_LIGHTMAPALPHA)
            float4 albedoTexture = lerp(    tex2D( g_diffuseMap, inData.uv0.xy ), 
                                            tex2D( g_diffuse2Map, inData.uv0.xy ), 
                                            lightMapColor.a);
        #else
            float4 albedoTexture = tex2D( g_diffuseMap, inData.uv0.xy );
        #endif
        
        albedo*=albedoTexture.rgb;
                
        #if !defined(_ALPHACAMERALIGHTMASK) && !defined(_TRANSLUCENCY) && !defined(_ALPHAENVIROMENTMASK)
            opacity*=albedoTexture.a;
        #endif  
    #endif
    
    #if defined(_MAP_DIFFUSE) && defined( _TRANSLUCENCY)
        #define translucencyColor albedoTexture.a
    #else
        float translucencyColor = 0;
    #endif
    
    float3  normal = normalize(inData.normal);
    
    /// Calculate lighting
    // First we proceed with static lighting (lightmaps)
    
    // For the case of having a directional light with shadow, we
    // need the shadow value to apply it to the light map, before applying the ligh
    #ifdef __USE_SHADOWMAP 
        #if defined ( _LIGHT0_DIRECTIONAL )
            float shadow = GetShadowDirectional(inData.shadowProjection);   
        #elif defined (_LIGHT0_POINT )
            float shadow = GetShadowPoint(inData.vpos.xyz);
        #endif
    #endif
    
    /// First apply the light from the lightmap
    #ifdef _MAP_LIGHTMAP
        outResult.color.rgb = 2.0f * albedo * lightMapColor.rgb;
        #ifdef _SHADOWLIGHTMAP
            outResult.color.rgb*=shadow;
        #endif
    #else
        outResult.color.rgb = 0;
    #endif
    
    // Now proceed with dynamic lighting
    // We will acumulate the diffuse light on myLight and the specular light on mySpecular
    float   fNDotL      = 0;
    float3  myLight     = 0;
    float3  fvLightDir  = 0;
    float3  mySpecular  = 0;
    float3  view        = 0;
    
    #if !defined(_MATERIAL_NOSPECULAR)
        view = normalize(inData.view);
    #endif
    
    /// Calculate directional lighting      
    #if defined (_LIGHT0_DIRECTIONAL) && !defined(_ONLYSHADOW)
        LightDirectional_PVL_PS(-g_lightDirection0.xyz, normal, view, g_lightColor0.xyz, translucencyColor, g_lightSpecular0.xyz, myLight, mySpecular);
        
        #ifdef __USE_SHADOWMAP      
            myLight *= shadow;
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif

    #endif
    
    #ifdef _LIGHT1_DIRECTIONAL      
        LightDirectional_PVL_PS(-g_lightDirection1.xyz, normal, view, g_lightColor1.xyz, translucencyColor, g_lightSpecular1.xyz, myLight, mySpecular);     
    #endif

    #ifdef _LIGHT2_DIRECTIONAL
        LightDirectional_PVL_PS(-g_lightDirection2.xyz, normal, view, g_lightColor2.xyz, translucencyColor, g_lightSpecular2.xyz, myLight, mySpecular);
    #endif

    #ifdef _LIGHT3_DIRECTIONAL
        LightDirectional_PVL_PS(-g_lightDirection3.xyz, normal, view, g_lightColor3.xyz, translucencyColor, g_lightSpecular3.xyz, myLight, mySpecular);     
    #endif
    
    #define myAmbientLight g_ambient.rgb    
    
    /// Calculate point lights
    #if defined (_LIGHT0_POINT) && !defined(_ONLYSHADOW)
        AddPointLightContributionWorldSpace(g_lightPosition0.xyz, g_lightPosition0.w, g_lightColor0.rgb, g_lightSpecular0.rgb,
                                            normal, view, inData.vpos.xyz, myLight, mySpecular );
        #ifdef __USE_SHADOWMAP
            myLight *= shadow;
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
    #endif
    
    #ifdef _LIGHT1_POINT
        AddPointLightContributionWorldSpace(g_lightPosition1.xyz, g_lightPosition1.w, g_lightColor1.rgb, g_lightSpecular1.rgb,
                                            normal, view, inData.vpos.xyz, myLight, mySpecular );
    #endif
    
    #ifdef _LIGHT2_POINT
        AddPointLightContributionWorldSpace(g_lightPosition2.xyz, g_lightPosition2.w, g_lightColor2.rgb, g_lightSpecular2.rgb,
                                            normal, view, inData.vpos.xyz, myLight, mySpecular );
    #endif

    #ifdef _LIGHT3_POINT
        AddPointLightContributionWorldSpace(g_lightPosition3.xyz, g_lightPosition3.w, g_lightColor3.rgb, g_lightSpecular3.rgb,
                                            normal, view, inData.vpos.xyz, myLight, mySpecular );       
    #endif

    #ifdef _NON_LIGHTED
        myLight = 1;
    #endif

    outResult.color.rgb += albedo * (myLight * g_diffuseColor.rgb + myAmbientLight * g_ambientColor.rgb);
        
    /// If we got a specular map then proceed to get the specular color from it 
    #ifndef _MATERIAL_NOSPECULAR
        float3 mySpecularColor = g_specularColor.rgb;
        #ifdef _MAP_SPECULAR
            mySpecularColor *= tex2D(g_specularMap,inData.uv0.xy ).rgb;
        #endif
        outResult.color.rgb+= mySpecular * mySpecularColor;
    #endif
    
    
    /// Apply the enviromental using the gloss map
    #ifdef _MAP_PLANAR_REFLECTION
        float3 reflection = tex2D(g_planarReflection, inData.uv1.xy/inData.uv1.z);

        #ifdef _MAP_ENVIROMENTGLOSS
            reflection *= tex2D( g_glossMap, inData.uv0.xy );
        #endif
        
        outResult.color.rgb += reflection;
    #else
        #ifdef _MAP_ENVIROMENT
            #ifdef _MAP_ENVIROMENT_CUBE
                float3 enviroment = texCUBE( g_enviromentMap, inData.uv1.xyz );
            #else
                float3 enviroment = tex2D( g_enviromentMap, inData.uv1.xy );
            #endif
        
            #ifdef _MAP_ENVIROMENTGLOSS
                enviroment *= tex2D( g_glossMap, inData.uv0.xy );
            #endif
        
            outResult.color.rgb += enviroment * g_enviromentColor.rgb;
        #endif
    #endif

    
    /// Apply emissive material color and map
    /// Then saturate the color
    outResult.color.rgb +=g_emissiveColor.rgb;
    #ifdef _MAP_EMISSIVE
        #ifdef _EMISSIVE_FLIPBOOK
            float2 euv = inData.uv0.xy * g_textureTransform5.xy + g_textureTransform5.zw;
            outResult.color.rgb+= tex2D( g_emissiveMap, euv).rgb;
        #else
            outResult.color.rgb+= tex2D( g_emissiveMap, inData.uv0.xy).rgb;
        #endif
    #endif

    float fogValue;
    #ifdef _VERTICAL_FOG
        fogValue = saturate( (inData.vpos.y - g_verticalFogValues.x) / g_verticalFogValues.z);
        outResult.color.rgb =   lerp(g_verticalFogColor.rgb, outResult.color.rgb, fogValue);
    #endif
    
    #ifdef _PIXEL_FOG
        ComputeFog(outResult.color,g_pixelFogColor.rgb,distance(g_cameraPos.xyz, inData.vpos.xyz),g_pixelFogOptions.x,g_pixelFogOptions.z);
    #endif
    
    // Calculate the output alpha from the calculated opacity and from the material diffuse color
    outResult.color.a = opacity * g_diffuseColor.a;
    
    #ifdef _CAMERA_LIGHT
        float vdn = abs(dot(g_cameraDir,normal));
        vdn = saturate(vdn);
        vdn = 1 - vdn;
        vdn *= vdn;
        #ifdef _ALPHACAMERALIGHTMASK
            vdn *= albedoTexture.a;     
        #endif
        outResult.color.rgb += vdn * g_cameraLightColor.rgb;
    #endif

    #if defined(_RIM_FADING)
        outResult.color.a*=GetRimFading(g_cameraPos.xyz,inData.vpos.xyz,normal,g_RimFading.y);
    #endif

#else//POINTSPRITE
    
    float2 uv = inData.uv;
    outResult.color = tex2D( g_diffuseMap, uv);

#endif
}

///////////////////////////////////////////////
// Spot Per Vertex PixelShader
///////////////////////////////////////////////
void MultilayerPVLSpot_MainPS( MultilayerPVLSpot_OuputVS inData,out MultilayerPVL_OutputPS outResult)
{   
    outResult = (MultilayerPVL_OutputPS)0;

    outResult.color = inData.color;
    float4 diffuseColor = tex2D( g_diffuseMap, inData.uv0.xy );
    
    /////// Calculate lighting
    float   fNDotL;
    float   fNDotLSpot;
    float3  myLight = 0;
    float3  fvLightDir;
    float   factor;
    float4  lightColor;
    float3  Half;
    float3  mySpecular  = 0;

    float3 view = 0;
    
    #if !defined(_MATERIAL_NOSPECULAR)
        view    = normalize(inData.view);
    #endif
    
    inData.normal   = normalize(inData.normal);
    
    #ifdef _LIGHT0_SPOT
        fvLightDir = g_lightPosition0.xyz - inData.vpos;
        if(dot(normalize(fvLightDir),-g_lightDirection0.xyz)>0)
            LightSpot_PVL_PS(normalize(inData.lightDir0.xyz), inData.normal, view, inData.lightDir0.w, g_lightColor0, g_lightSpecular0, myLight, mySpecular, g_spot1Map, inData.spotProjection1);
        
        #ifdef __USE_SHADOWMAP
            float shadow = GetShadowSpot(inData.shadowProjection);
            myLight *= shadow;
        
            #ifndef _MATERIAL_NOSPECULAR
                mySpecular *= shadow;
            #endif
        #endif
    #endif  
    
    #ifdef _LIGHT1_SPOT
        fvLightDir = g_lightPosition1.xyz - inData.vpos;
        if(dot(normalize(fvLightDir),-g_lightDirection1.xyz)>0)
            LightSpot_PVL_PS(normalize(inData.lightDir1.xyz), inData.normal, view, inData.lightDir1.w, g_lightColor1, g_lightSpecular1, myLight, mySpecular, g_spot2Map, inData.spotProjection2);
    #endif  
    
    outResult.color.rgb = myLight * diffuseColor.rgb * g_diffuseColor.rgb;

    /// If we got a specular map then proceed to get the specular color from it 
    #ifndef _MATERIAL_NOSPECULAR
        #ifdef _MAP_SPECULAR
            mySpecular  *= tex2D(g_specularMap,inData.uv0.xy ).rgb;
        #endif
        outResult.color.rgb += mySpecular;
    #endif
    
    /// Apply alpha from the material diffuse color
    outResult.color.a = inData.color.a * g_diffuseColor.a * diffuseColor.a;

    #if defined(_RIM_FADING)
        outResult.color.a*=GetRimFading(g_cameraPos.xyz,inData.vpos.xyz,inData.normal,g_RimFading.y);
    #endif
}

#endif

#define _SIMPLE_CGFX

// In the case low, med or high shadows are used, we are using shadows!
#if defined (_SHADOW_LOW) || defined (_SHADOW_MED) || defined(_SHADOW_HI)
    #define __USE_SHADOWMAP
#endif



//////////////////////////////////////
// MATRIX MULTIPLICATION
//////////////////////////////////////
float3 Transform(float3x3 mat, float3 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif
}

float4 Transform(float4x4 mat, float4 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

float2 Transform(float2x2 mat, float2 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

//this conversion will not deal with renormalizations because is a bad way to handle bad data passing to the shader.
//the main problem is that cg-compiler isn't as smart as hlsl-compiler dealing with already normalized vectors
float3x3 GetWorldToTangentMatrix(float3x3 worldmtx,float3 tangent, float3 normal)
{
    float3x3 worldToTangent = 0;
    worldToTangent[0] = normalize(Transform(worldmtx, tangent));
    worldToTangent[2] = normalize(Transform(worldmtx, normal));
    worldToTangent[1] = normalize(cross(worldToTangent[0], worldToTangent[2]));    

    return worldToTangent;
}

float4 TransformPlanarReflection(float4 inPos)
{
    float4x4    matTexScale = 0;

#if !defined(_GCM)
    matTexScale._m00 = 0.5f;
    matTexScale._m11 =  -.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m03 = 0.5f; 
    matTexScale._m13 = 0.5f;
    matTexScale._m23 = 1.0f; 
    matTexScale._m33 = 1.0f;
#else
    matTexScale._m00 = 0.5f;
    matTexScale._m11 = -0.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m30 = 0.5f; 
    matTexScale._m31 = 0.5f;
    matTexScale._m32 = 1.0f; 
    matTexScale._m33 = 1.0f;
#endif

    return Transform(matTexScale,inPos);
}

uniform float4x4    g_skinMatrix[_MAXBONES];        ///< 128 Registers for skin bones

struct SKINVERTEX
{
    float4 P;
    float3 N;
    float3 T;
};

SKINVERTEX SkinVertex(float3 p, float3 n, float3 t, float4 indices, float4 weights)
{
    SKINVERTEX Out = (SKINVERTEX) 0;
    for(int i = 0; i < 4; i++)
    {
        Out.P.xyz += Transform(g_skinMatrix[indices.x], float4(p,1)).xyz * weights.x;
        Out.N += (float3)(Transform((float3x3) g_skinMatrix[indices.x], n) * weights.x);

        #if !defined(SH_VERSION_SH1)
        Out.T += (float3)(Transform((float3x3) g_skinMatrix[indices.x], t) * weights.x);
        #endif

        indices.xyzw = indices.yzwx;
        weights.xyzw = weights.yzwx;
    }

    Out.P.w = 1;
    Out.N = (float3)normalize(Out.N);
    
    #if !defined(SH_VERSION_SH1)
    Out.T = (float3)normalize(Out.T);
    #endif

    return Out;
}


//////////////////////////////////////
// VERTEX SHADER INPUT
//////////////////////////////////////
struct VSINPUT
{
    float4 pos      : POSITION;         ///< Vertex position
    
#ifdef _USE_SKINMATRIX
    float4 weight   : BLENDWEIGHT;
    float4 indices  : BLENDINDICES;
#endif

#ifdef _HAS_NORMAL
    float3 normal   : NORMAL;           ///< Vertex Normal
#endif

#ifdef _HAS_COLOR
    float4 color    : COLOR0;           ///< Diffuse color of the vertex
#endif
    
    float2 uv0      : TEXCOORD0;        ///< UV Coordinates for diffuse, enviroment and normal map

    #ifdef _HAS_UV1
        float2 uv1      : TEXCOORD1;        ///< UV Coordinates
    #endif
};
//////////////////////////////////////
// END VERTEX SHADER INPUT
//////////////////////////////////////

//////////////////////////////////////
// VERTEX SHADER OUTPUT
//////////////////////////////////////
struct VSOUTPUT
{
    float4 hpos         : POSITION;     ///< Clip space transformed vertex position
    float4 color        : COLOR0;       ///< Vertex color
    float4 specular     : COLOR1;

#ifdef _PS3
    float3 uv0          : TEXCOORD0;    ///< UV Coordinates used by the diffuse texture
#else
    float3 uv0          : TEXCOORD0_centroid;   ///< UV Coordinates used by the diffuse texture
#endif
    float3 uv1          : TEXCOORD1;
#ifdef _PS3
    float4 vpos         : TEXCOORD2;    ///< Position of the vertex in world space, and shadowprojection distance
#else
    float4 vpos         : TEXCOORD2_centroid;   ///< Position of the vertex in world space, and shadowprojection distance
#endif

#ifdef _LIGHT0_SPOT
    float4 spot1Projection  : TEXCOORD3;    ///< Shadow map projection
#endif

#ifdef _LIGHT1_SPOT
    float4 spot2Projection  : TEXCOORD4;    ///< Shadow map projection
    float4 color2           : TEXCOORD5;        
    float4 specular2        : TEXCOORD6;        
#endif
    
#if defined(__USE_SHADOWMAP) && (defined(_LIGHT0_DIRECTIONAL) || defined(_LIGHT0_SPOT))
#ifdef _PS3
    float4 shadowProjection : TEXCOORD4;    ///< Shadow map projection
#else
    float4 shadowProjection : TEXCOORD4_centroid;   ///< Shadow map projection
#endif
#endif

    float4 refl     : TEXCOORD7;        ///< UV Coordinates
};
//////////////////////////////////////
// END VERTEX SHADER OUTPUT
//////////////////////////////////////


//////////////////////////////////////
// LIGHTING
//////////////////////////////////////

/// Tongas upload variables
float4      g_ambient;
float4      g_ambientColor;
float4      g_diffuseColor;
float4      g_emissiveColor;
float4      g_specularColor;


//////////////////////////////////////
// LIGHTING INFO
float4      g_lightDirection0;
float4      g_lightPosition0;
float4      g_lightColor0;
float4      g_lightSpecular0;

#if defined(_LIGHT1_POINT) || defined(_LIGHT1_DIRECTIONAL) || defined(_LIGHT1_SPOT)
    float4      g_lightDirection1;
    float4      g_lightPosition1;
    float4      g_lightColor1;
    float4      g_lightSpecular1;
#endif


//////////////////////////////////////
// LIGHTING FUNCTIONS
void LightSpot_VS(float3 iDir, float Range, float3 normal, float3 view, float3 iD, float4 iS, inout float3 oD, inout float3 oS)
{
    float3 Factor = length(iDir.xyz);
    Factor = ( 1.0f - (Factor  / Range) );                      

    float3 fvLightDir = normalize(iDir);
    float fNDotL = dot(normal, fvLightDir);     

    oD += iD * saturate(fNDotL) * Factor;
    
    #ifndef _MATERIAL_NOSPECULAR
        float3 Half = normalize(fvLightDir+view);
        oS += Factor * iS.xyz * pow(saturate(dot(Half,normal)), g_specularColor.a);
    #endif  
}

//////////////////////////////////////
// END LIGHTING
//////////////////////////////////////


uniform float4x4    g_matTextureProjection;
uniform float4      g_shadowmapOptions;
uniform float4      g_texelSize89;

#define     g_ShadowmapFactor   (1-g_shadowmapOptions.x)    /// default 0.0
#define     g_ShadowmapZBias    (g_shadowmapOptions.y)      /// default -0.001

uniform sampler2D   g_shadowMap         : register(s9);
uniform samplerCUBE g_shadowCubeMap     : register(s9);

////////////////////////////////////
// DIRECTIONAL
float SampleShadowTest(float4 ShadowTexC)
{   
    #if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI
        return tex2D(g_shadowMap, ShadowTexC.xy).r >= ShadowTexC.z;     
    #else   //nVidia
        return tex2Dproj(g_shadowMap, ShadowTexC).r;
    #endif  
}

float GetShadowDirectional(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.f - ShadowTexC.y;

#ifdef _PS3
    ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _XENON
    ShadowTexC.xyz = ShadowTexC.xyz / ShadowTexC.w;
    
    // [BP] On xbox360 we are getting projected distances that are higher than 1
    // as they are not being cut by the far plane of the light frustum
    // still we need to study more this effect, even check if it can be done on vertex
    // shader stage to save gpu process
    ShadowTexC.z = min(1,ShadowTexC.z);     // Check that z the minimum value to 1
#endif
    
#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
    
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.w = 1;
            
    #if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)
        return saturate(SampleShadowTest(ShadowTexC) + g_ShadowmapFactor);
    #else

        float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 2;
        float4 tY = float4(0, g_texelSize89.w, 0, 0) * 2;
        float accum = 0;
 
        #if defined(_SHADOW_MED)
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY * -.5);
            accum += SampleShadowTest(ShadowTexC + tX * -.5 + tY *  .5);
            accum += SampleShadowTest(ShadowTexC + tX *  .5 + tY *  .5);
            return saturate((accum/4.f) + g_ShadowmapFactor);
        #elif defined(_SHADOW_HI)
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY * -1);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  0);
            accum += SampleShadowTest(ShadowTexC + tX * -1 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  0 + tY *  1);
            accum += SampleShadowTest(ShadowTexC + tX *  1 + tY *  1);  
            return saturate((accum/9.f) + g_ShadowmapFactor);
        #else
            return 1;
        #endif
    #endif  
}

/////////////////////////////////
// SPOT
//[VC]: why this is just a copy paste from spotdirectional???
float GetShadowSpotSample(float4 ShadowTexC)
{
    float shadow;

#if defined(_XENON) || defined(_SHADOWMAP_FLOAT)    //Xenon & ATI

    float a = tex2D(g_shadowMap, ShadowTexC.xy).r > ShadowTexC.z;
    float b = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, 0)).r > ShadowTexC.z;
    float c = tex2D(g_shadowMap, ShadowTexC.xy + float2(0, g_texelSize89.w)).r > ShadowTexC.z;
    float d = tex2D(g_shadowMap, ShadowTexC.xy + float2(g_texelSize89.z, g_texelSize89.w)).r > ShadowTexC.z;

#if defined(SH_VERSION_SH2)
    return a;
#endif
    
    // transform to texel space
    float2 texelpos = (1.f/g_texelSize89.zw) * ShadowTexC;
    
    // Determine the lerp amounts           
    float2 lerps = frac( texelpos );

    // lerp between the shadow values to calculate our light amount
    shadow = lerp( lerp( a, b, lerps.x ),
                   lerp( c, d, lerps.x ),
                   lerps.y );       
    return shadow;

#else   //nVidia

    shadow = tex2Dproj(g_shadowMap, ShadowTexC).r;

#endif
    
    return shadow;
}

float GetShadowSpot(float4 TexCoords)
{
    float4 ShadowTexC = TexCoords;
    ShadowTexC.xy = 0.5 * TexCoords.xy / TexCoords.w + float2( 0.5, 0.5 );
    ShadowTexC.y = 1.0f - ShadowTexC.y;

    //not needed for spot lights
#ifdef _PS3
    //ShadowTexC.z = ShadowTexC.z * .5f + .5f;
#endif

#ifdef _DEBUG_SHADOWMAPS    
    //Dark regions out of shadow projection
    if(ShadowTexC.x < 0 ||
        ShadowTexC.y < 0 ||
        ShadowTexC.x > 1 ||
        ShadowTexC.y > 1)
        return 0;
#endif
        
    ShadowTexC.z += g_ShadowmapZBias;
    ShadowTexC.z /= ShadowTexC.w;

    ShadowTexC.w = 1;
            
#if defined(SH_VERSION_SH2) || defined(_SHADOW_LOW)

    return saturate(GetShadowSpotSample(ShadowTexC) + g_ShadowmapFactor);
    
#endif

    float4 tX = float4(g_texelSize89.z, 0, 0, 0) * 1;
    float4 tY = float4(0, g_texelSize89.w, 0, 0) * 1;

    float accum = 0;

#if defined(_SHADOW_MED)
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY * -.5);
    accum += GetShadowSpotSample(ShadowTexC + tX * -.5 + tY *  .5);
    accum += GetShadowSpotSample(ShadowTexC + tX *  .5 + tY *  .5); 
    return saturate((accum/4.f) + g_ShadowmapFactor);
#endif
    
#if defined(_SHADOW_HI)
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY * -1);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  0);
    accum += GetShadowSpotSample(ShadowTexC + tX * -1 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  0 + tY *  1);
    accum += GetShadowSpotSample(ShadowTexC + tX *  1 + tY *  1);
    return saturate((accum/9.f) + g_ShadowmapFactor);
#endif

    return 1;
}


/////////////////////////////////
// POINT

float GetShadowPointSample(float3 Pos)
{
    float shadow = 1;

#ifdef _LIGHT0_POINT
    shadow = texCUBE(g_shadowCubeMap, Pos.xyz-g_lightPosition0.xyz).r > (length(Pos.xyz-g_lightPosition0.xyz) * g_lightPosition0.w) + g_ShadowmapZBias;
#endif

    return shadow;
}

float GetShadowPoint(float3 Pos)
{
    return saturate(GetShadowPointSample(Pos) + g_ShadowmapFactor);
}


//////////////////////////////////////
//VERTEX SHADER
//////////////////////////////////////

//////////////////////////////////////
// VERTEX SHADER CONSTANTS
//float4x4  g_matWorld, g_matWorldTR, g_matWorldView, g_matWorldViewIT, g_matWorldViewProjection;
float4x4    g_matWorld, g_matWorldView, g_matWorldViewProjection;
float4x4    g_matTexture0, g_matTexture1, g_matTexture2, g_matTexture3;
float4      g_cameraPos;



//////////////////////////////////////
// VERTEX SHADER
VSOUTPUT main_VS(VSINPUT IN)
{
    VSOUTPUT OUT = (VSOUTPUT) 0;
    
    OUT.color   = float4(1,1,1,1);
    float3 normal = float3(0,0,1);
        
    #ifdef _HAS_NORMAL
        normal = normalize(IN.normal);
    #endif
        
    #ifdef _HAS_COLOR
        OUT.color   = IN.color;
    #endif
    
    
    #ifdef _USE_SKINMATRIX  
        SKINVERTEX v = SkinVertex(IN.pos, normal,0, IN.indices, IN.weight);

        float4 position = v.P;
        normal = v.N;
    #else
        float4 position = IN.pos;
    #endif //_USE_SKINMATRIX

    
    /// Transform the position to clip space
    OUT.hpos    = Transform(g_matWorldViewProjection, position);
    OUT.vpos    = Transform(g_matWorld, position);
    
    OUT.uv0 = float3(IN.uv0, 1);
    OUT.uv1 = float3(IN.uv0, 1);

    #ifdef _HAS_UV1
        OUT.uv1 = float3(IN.uv1, 1);
    #endif

#ifndef _NON_LIGHTED

    float   fNDotL      = 0;
    float3  myLight     = 0;
    float3  fvLightDir  = 0;
    float   lightFactor = 0;

    float3  Half        = 0;
    float3  mySpecular  = 0;
    float3  view        = -normalize(OUT.vpos-g_cameraPos);

    
    #ifdef _LIGHT0_DIRECTIONAL      
        fNDotL      = dot(normal, -g_lightDirection0);      
        myLight     += g_lightColor0.rgb * saturate(max(0, fNDotL));
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(-g_lightDirection0 + view);    
            mySpecular  += g_lightSpecular0 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
    
        #ifdef __USE_SHADOWMAP
            OUT.shadowProjection = Transform(g_matTextureProjection, float4(position.xyz,1));
        #endif
    #endif

    #ifdef _LIGHT1_DIRECTIONAL      
        fNDotL      = dot(normal, -g_lightDirection1);      
        myLight     += g_lightColor1.rgb * saturate(max(0, fNDotL));
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(-g_lightDirection1 + view);    
            mySpecular  += g_lightSpecular1 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
        
    #endif
    
    #ifdef _LIGHT0_POINT
        lightFactor = length(g_lightPosition0.xyz - OUT.vpos);
        lightFactor = saturate(1.0f - (lightFactor  / g_lightPosition0.w));
        
        fvLightDir = normalize(g_lightPosition0.xyz - OUT.vpos);        
        fNDotL = dot(normal, fvLightDir);       
        myLight += g_lightColor0.rgb * saturate(max(0, fNDotL)) * lightFactor;              
        
        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(fvLightDir+view);
            mySpecular  += lightFactor * g_lightSpecular0 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif

    #endif
    
    #ifdef _LIGHT1_POINT
        lightFactor = length(g_lightPosition1.xyz - OUT.vpos);
        lightFactor = saturate(1.0f - (lightFactor  / g_lightPosition1.w));

        fvLightDir  = normalize(g_lightPosition1.xyz - OUT.vpos);       
        fNDotL      = dot(normal, fvLightDir);      
        myLight += g_lightColor1.rgb * saturate(max(0, fNDotL)) * lightFactor;              

        #ifndef _MATERIAL_NOSPECULAR
            Half = normalize(fvLightDir+view);
            mySpecular += lightFactor * g_lightSpecular1 * pow(max(0, dot(Half,normal)), g_specularColor.a);
        #endif
    #endif


    #ifdef _LIGHT0_SPOT
        OUT.color.xyz = OUT.specular.xyz = 0;
        
        LightSpot_VS(g_lightPosition0.xyz - OUT.vpos.xyz, g_lightPosition0.w, normal, view, g_lightColor0.rgb, g_lightSpecular0, OUT.color.xyz, OUT.specular.xyz);

        OUT.spot1Projection = Transform(g_matTexture2, float4(position.xyz,1));

        OUT.color *= g_diffuseColor;
        OUT.specular *= g_specularColor;

        #ifdef __USE_SHADOWMAP
            OUT.shadowProjection = Transform(g_matTextureProjection, float4(position.xyz,1));
        #endif
    #endif

    #ifdef _LIGHT1_SPOT
        OUT.color2.xyz = OUT.specular2.xyz = 0;
        
        LightSpot_VS(g_lightPosition1.xyz - OUT.vpos.xyz, g_lightPosition1.w, normal, view, g_lightColor1.rgb, g_lightSpecular0, OUT.color2.xyz, OUT.specular2.xyz);

        OUT.spot2Projection = Transform(g_matTexture3, float4(position.xyz,1));
        
        OUT.color2 *= g_diffuseColor;
        OUT.specular2 *= g_specularColor;
    #endif
    
    #ifndef _LIGHT0_SPOT
        OUT.color.rgb *= myLight * g_diffuseColor;
    
        #ifndef _MATERIAL_NOSPECULAR
            OUT.specular.rgb = mySpecular * g_specularColor.rgb;
        #endif
    #endif
    
#else
    
    OUT.color.rgb = g_diffuseColor;
    
#endif //_NON_LIGHTED

    OUT.color.a = g_diffuseColor.a;
    
    return( OUT );
}

//////////////////////////////////////
// END VERTEX SHADER
//////////////////////////////////////


//////////////////////////////////////
//PIXEL SHADERS
//////////////////////////////////////

//////////////////////////////////////
// SAMPLERS
sampler     g_layer0            : register(s0);
sampler     g_spotMap1          : register(s8);
sampler     g_spotMap2          : register(s9);


///////////////////////////////////////////////
// PIXEL SHADER
///////////////////////////////////////////////
float4 main_PS( VSOUTPUT IN
                #if defined(_MRT1)
                ,out float4 oColor1 : COLOR1
                #endif
                #if defined(_MRT2)
                ,out float4 oColor2 : COLOR2
                #endif
                #if defined(_MRT3)
                ,out float4 oColor3 : COLOR3
                #endif
               )    : COLOR0
{
    float3 shadow = 1;
    
    float4 OUT = 0;

    float4 Layer0 = tex2D(g_layer0, IN.uv0);
    
    OUT.a = IN.color.a * Layer0.a;
    
    #ifndef _LIGHT0_SPOT

        OUT.rgb = IN.color * Layer0;

        #ifndef _MATERIAL_NOSPECULAR
            OUT.rgb += IN.specular.xyz;
        #endif
        
        #ifdef __USE_SHADOWMAP

            #ifdef _LIGHT0_DIRECTIONAL
                shadow = GetShadowDirectional(IN.shadowProjection);
            #endif

            #ifdef _LIGHT0_POINT
                shadow = GetShadowPoint(IN.vpos.xyz);
            #endif          
            
        #endif
    #endif

    #ifdef _LIGHT0_SPOT
        
        float3 spot1 = tex2Dproj(g_spotMap1, IN.spot1Projection);
        OUT.rgb = IN.color * spot1 * Layer0;

        #ifndef _MATERIAL_NOSPECULAR
            OUT.rgb += IN.specular.xyz * spot1;
        #endif

        #ifdef __USE_SHADOWMAP
            shadow = GetShadowSpot(IN.shadowProjection);
        #endif

    #endif

    #ifdef _LIGHT1_SPOT

        float3 spot2 = tex2Dproj(g_spotMap2, IN.spot2Projection);
        
        OUT.rgb += IN.color2 * spot2 * Layer0;

        #ifndef _MATERIAL_NOSPECULAR
            OUT.rgb += IN.specular2.xyz * spot2;
        #endif

    #endif
    
    #ifdef __USE_SHADOWMAP
    
        #ifndef _LIGHT0_SPOT
            shadow += Layer0 * g_ambient.rgb * g_ambientColor;
        #endif
        
        OUT.rgb *= shadow;
        
    #elif !defined(_LIGHT0_SPOT)
        
        OUT.rgb += Layer0 * g_ambient.rgb * g_ambientColor;
        
    #endif

    return OUT;
}

struct VSI_SCREEN
{
    float4 pos      : POSITION;
    float4 color    : COLOR0;
    float2 uv       : TEXCOORD0;
};

struct VSO_SCREEN
{
    float4 pos      : POSITION;
#ifdef _PS3
    float2 uv       : TEXCOORD0;
#else
    float2 uv       : TEXCOORD0_centroid;
#endif
};


////////////////////////////////////////////////////
// bloom3_filterScreen
////////////////////////////////////////////////////
sampler sceneTexture            : register(s0);
sampler brightTexture           : register(s1);

#ifndef _GCM
float4 g_screenFilterValues[9]; ///< 9 tap distance filter values
#else
DECLARE_GCM_FILTERVALUES9
#endif
float4 g_bloomBrightness;       ///< Brightness fitering options
float4 g_texelSize01;

VSO_SCREEN vsFilterScreen( VSI_SCREEN IN )
{
    VSO_SCREEN OUT  = (VSO_SCREEN) 0;        
    OUT.pos         = IN.pos;
    OUT.uv          = IN.uv;
    return OUT;
}

float4 psFilterScreen( VSO_SCREEN IN
                        #if defined(_MRT1)
                        ,out float4 oColor1 : COLOR1
                        #endif
                        #if defined(_MRT2)
                        ,out float4 oColor2 : COLOR2
                        #endif
                        #if defined(_MRT3)
                        ,out float4 oColor3 : COLOR3
                        #endif
                      ) : color
{
    #ifdef _GCM
    INIT_GCM_FILTERVALUES9
    #endif
    float4  color = { 0.0f, 0.0f, 0.0f, 0.0f };
    float2 uv;
    
    /// Compine the textures in a 9 tap distance filter
    //float totalLum = 0;
    for( int i = 0; i < 9; i++ )
    {
        uv = IN.uv + g_screenFilterValues[i].xy * 2 + 2 *g_texelSize01.xy;
        color += tex2D( sceneTexture,  uv) *
                 tex2D( brightTexture, uv).g;                
    //  totalLum +=(color.r+color.g+color.b) *0.33; 
    }
    
    color /= 9; //totalLum; //9.0f;
    /// Determine the brightness of this particular pixel. 
    float luminance = dot( color.rgb, g_bloomBrightness.rgb);
    
    /// If this pixel satisfies the bright pass threshold it will
    /// be > 0.0 after this operation
    luminance = max( 0.0f, luminance - g_bloomBrightness.w);
    
    /// Muliply by the above predicate, use the sign() intrinsic
    /// to make sure that luminance is either 0.0 or 1.0, thus not
    /// scaling any bright pixels that are needed.
    color.rgb *= sign( luminance );
    
    /// Write the colour to the bright-pass render target
    color.a = 1.0f;
    
    return color;
}



////////////////////////////////////////////////////
// bloom3_gaussian
////////////////////////////////////////////////////
struct VS_OUTPUT
{
    float4  pos         : POSITION;
    float2  uv          : TEXCOORD0;
};

sampler tex0 : register( s0 );          ///< Whatever texture is set using IDirect3DDevice9::SetTexture( 0, ... )

// -------------------------------------------------------------
// vertex shader function (input channels)
// -------------------------------------------------------------
VS_OUTPUT vsGaussianBlur(float4 pos : POSITION, float2 uv : TEXCOORD0)
{
    VS_OUTPUT Out;
    Out.pos.xy  = pos.xy;
    Out.pos.z   = 0.5f;
    Out.pos.w   = 1.0f;
    Out.uv      = uv;
    return Out;
}

float4 psGaussianBlur( in float2 t : TEXCOORD0 
                        #if defined(_MRT1)
                        ,out float4 oColor1 : COLOR1
                        #endif
                        #if defined(_MRT2)
                        ,out float4 oColor2 : COLOR2
                        #endif
                        #if defined(_MRT3)
                        ,out float4 oColor3 : COLOR3
                        #endif
                      ) : COLOR
{
    #ifdef _GCM
    INIT_GCM_FILTERVALUES9
    #endif
    
    float4 color = { 0.0f, 0.0f, 0.0f, 0.0f };  
    
    //float2 of = float2(g_texelSize01.x, - 1 * g_texelSize01.y);
       
    float fc = 0;
    float2 offset;
    /*
    for( int i = 0; i <3; i++ )
    {
        of.x = -1 * g_texelSize01.x;
    //    color += tex2D( tex0, float2(t.x,t.y) + tc + float2( g_screenFilterValues[i].x, g_screenFilterValues[i].y ) ) ; g_screenFilterValues[i].z;
        for (int j= 0; j < 3; j++)
        {
            of.x+= g_texelSize01.x;
            offset = of*5;
            color += tex2D( tex0, t + offset  + float2(g_texelSize01.x*2, g_texelSize01.y*2)); 
    
        }
        of.y +=g_texelSize01.y;
    }       
    
    
    /*
    float2 circle[9] = {
    float2 (-1,-1),
    float2 (0,-1),
    float2 (1, -1),
    float2 (-1,0),
    float2 (0,0),
    float2 (1, 0),
    float2 (-1,1),
    float2 (0,1),
    float2 (1, 1)
    };
    
    float factor[9] = {
    3,9,3,
    9,1,9,
    3,9,3
    };
    /**/
    
    float2 of = float2(g_texelSize01.x, 1 * g_texelSize01.y);
    
    for( int i = 0; i <9; i++ )
    {
        //color += tex2D( tex0, t + of * g_screenFilterValues[i].xy * g_screenFilterValues[i].w + float2(g_texelSize01.x*2, g_texelSize01.y*2)) * g_screenFilterValues[i].z; 
        color += tex2D( tex0, t + of * g_screenFilterValues[i].xy * g_screenFilterValues[i].w + 2 * g_texelSize01.xy) * g_screenFilterValues[i].z; 
        //color += tex2D( tex0, t + of * circle[i]* 2 + float2(g_texelSize01.x*2, g_texelSize01.y*2)) * factor[i]; 
        fc+=g_screenFilterValues[i].z;
        //fc+=factor[i];
    }
    
    color/=fc;
    color.a = 1;
    return color;
}
    


////////////////////////////////////////////////////
// bloom3_render
////////////////////////////////////////////////////
sampler bloom               : register(s0);
sampler original_scene      : register(s1);
sampler blur                : register(s2);
sampler focusBlur           : register(s3);
float4  g_bloomRenderOptions;
float4 g_auxiliary0;

#define g_exposure      g_bloomRenderOptions.x
#define g_blendFactor   g_bloomRenderOptions.y
#define g_doBlur        g_bloomRenderOptions.z
#define g_blurEffect    g_bloomRenderOptions.w

VSO_SCREEN vsRenderBloom( VSI_SCREEN IN )
{
    VSO_SCREEN OUT = (VSO_SCREEN) 0;        
    OUT.pos     = IN.pos;
    OUT.pos.z   = 0.5f;
    OUT.pos.w   = 1;
    OUT.uv = IN.uv;
    return OUT;
}

float4 g_kernelValues;
//float4 g_texelSize01;

float4 psRenderBloom( in float2 t : TEXCOORD0
                        #if defined(_MRT1)
                        ,out float4 oColor1 : COLOR1
                        #endif
                        #if defined(_MRT2)
                        ,out float4 oColor2 : COLOR2
                        #endif
                        #if defined(_MRT3)
                        ,out float4 oColor3 : COLOR3
                        #endif
                        ) : COLOR0
{
    t.x+=sin(g_kernelValues.y+t.x*16) * g_texelSize01.z * 4 * g_blurEffect;
    t.y+=cos(g_kernelValues.y+t.y*16) * g_texelSize01.w * 4 * g_blurEffect;
    float4 c = tex2D( original_scene, t );  
    
    /// Apply focus blur effect
    if (g_doBlur > 0)
    {
        float blurV = tex2D(focusBlur,t).r;     
        if (blurV > 0)
        { 
            //blurV = blurV;
            c = lerp(c,tex2D(blur,t),blurV);        
        }
        
    }   
    
    c = c * g_exposure + g_blendFactor * tex2D( bloom, t);          
    /*
    c.r += sin(g_kernelValues.y*1.5) *0.5f * g_blurEffect;
    c.g += cos(g_kernelValues.y*2+23) * 0.5f * g_blurEffect;
    c.b += sin(g_kernelValues.y*1-15) * 0.5f * g_blurEffect;    
    /**/
    
    /**/
    c.r = lerp(c.r,1 - c.r,g_auxiliary0.x*0.5); 
    c.g = lerp(c.g,1 - c.g,g_auxiliary0.y*0.5);
    c.b = lerp(c.b,1 - c.b,g_auxiliary0.z*0.5);
    /**/
    
    
    c.a = 1.0f;     
    return c;
}


struct VSI_SCREEN
{
    float4 pos      : POSITION;
    float4 color    : COLOR0;
    float2 uv       : TEXCOORD0;
};

struct VSO_SCREEN
{
    float4 pos      : POSITION;
    float2 uv       : TEXCOORD0;
};


////////////////////////////////////////////////////
// Vertex Shaders
////////////////////////////////////////////////////
float4  g_bloomBrightness;

float4 g_texelSize01;

void main_VS(float4 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC[4] : TEXCOORD0)
{
    oPos = iPos;

    float2 texelSize = g_texelSize01.xy;

    float2 u = float2(1.f, 0) * g_bloomBrightness.w;
    float2 v = float2(0, 1.f) * g_bloomBrightness.w;    

    oTC[0] = (iTC - u - v) + texelSize.xy;
    oTC[1] = (iTC - u + v) + texelSize.xy;
    oTC[2] = (iTC + u - v) + texelSize.xy;
    oTC[3] = (iTC + u + v) + texelSize.xy;
}


void BrightPass_VS(float4 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC[2] : TEXCOORD0)
{
    oPos = iPos;

    float2 texelSize = g_texelSize01.xy;

    float2 u = float2(1.f, 0) * g_bloomBrightness.w;
    float2 v = float2(0, 1.f) * g_bloomBrightness.w;    

    oTC[0] = (iTC - u - v) + texelSize.xy;
    oTC[1] = (iTC - u + v) + texelSize.xy;  
}

void mainFinal_VS(float4 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC : TEXCOORD0,
          out float2 oTC1 : TEXCOORD1)
{
    oPos = iPos;
    
    oTC = iTC + (g_texelSize01.xy * .5f);
    oTC1 = iTC + (g_texelSize01.zw * .5f);
}



////////////////////////////////////////////////////
// Pixel Shaders
////////////////////////////////////////////////////
sampler Tex             : register(s0);
sampler Bloom           : register(s1);

float4 main_PS(     float2 iTC[4] : TEXCOORD0
                    #if defined(_MRT1)
                    ,out float4 oColor1 : COLOR1
                    #endif
                    #if defined(_MRT2)
                    ,out float4 oColor2 : COLOR2
                    #endif
                    #if defined(_MRT3)
                    ,out float4 oColor3 : COLOR3
                    #endif
               ) : COLOR0
{
    float3 colorSum = 0;
    
    for(int i = 0; i < 4; i++)
        colorSum += tex2D(Tex, iTC[i]).xyz * .25f;
    
    return float4(colorSum, 1);
}

float4 BrightPass_PS(float2 tc : TEXCOORD0,
                     float2 tc1 : TEXCOORD1
                    #if defined(_MRT1)
                    ,out float4 oColor1 : COLOR1
                    #endif
                    #if defined(_MRT2)
                    ,out float4 oColor2 : COLOR2
                    #endif
                    #if defined(_MRT3)
                    ,out float4 oColor3 : COLOR3
                    #endif
                     ) : COLOR0
{
    float3 c = tex2D(Tex, tc);
    
    if(dot(c, float3(.33,.33,.33)) < g_bloomBrightness.x)
        c = 0;
        
    return float4(c,1);
}

float4 FinalPass_PS(    float2 tc : TEXCOORD0,
                        float2 tc1 : TEXCOORD1
                        #if defined(_MRT1)
                        ,out float4 oColor1 : COLOR1
                        #endif
                        #if defined(_MRT2)
                        ,out float4 oColor2 : COLOR2
                        #endif
                        #if defined(_MRT3)
                        ,out float4 oColor3 : COLOR3
                        #endif
                 ) : COLOR0
{
    float3 b = tex2D(Bloom, tc1).rgb * g_bloomBrightness.y;

    return float4(b,1);
}


float4 g_texelSize01;

void main_VS(float3 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC : TEXCOORD0)
{
    oPos = float4(iPos.xyz, 1);
    oTC = iTC + g_texelSize01.xy * .5f;
}


sampler2D tex   : register(s0);
float4 g_specialVector1;

float4 main_PS( float2 tc : TEXCOORD0
                #if defined(_MRT1)
                ,out float4 oColor1 : COLOR1
                #endif
                #if defined(_MRT2)
                ,out float4 oColor2 : COLOR2
                #endif
                #if defined(_MRT3)
                ,out float4 oColor3 : COLOR3
                #endif
               ) : COLOR
{
    return float4(tex2D(tex, tc).xyz, g_specialVector1.w);
}

#define _DEPTH_OF_FIELD_CGFX

//////////////////////////////////////
// MATRIX MULTIPLICATION
//////////////////////////////////////
float3 Transform(float3x3 mat, float3 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif
}

float4 Transform(float4x4 mat, float4 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

float2 Transform(float2x2 mat, float2 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

//this conversion will not deal with renormalizations because is a bad way to handle bad data passing to the shader.
//the main problem is that cg-compiler isn't as smart as hlsl-compiler dealing with already normalized vectors
float3x3 GetWorldToTangentMatrix(float3x3 worldmtx,float3 tangent, float3 normal)
{
    float3x3 worldToTangent = 0;
    worldToTangent[0] = normalize(Transform(worldmtx, tangent));
    worldToTangent[2] = normalize(Transform(worldmtx, normal));
    worldToTangent[1] = normalize(cross(worldToTangent[0], worldToTangent[2]));    

    return worldToTangent;
}

float4 TransformPlanarReflection(float4 inPos)
{
    float4x4    matTexScale = 0;

#if !defined(_GCM)
    matTexScale._m00 = 0.5f;
    matTexScale._m11 =  -.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m03 = 0.5f; 
    matTexScale._m13 = 0.5f;
    matTexScale._m23 = 1.0f; 
    matTexScale._m33 = 1.0f;
#else
    matTexScale._m00 = 0.5f;
    matTexScale._m11 = -0.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m30 = 0.5f; 
    matTexScale._m31 = 0.5f;
    matTexScale._m32 = 1.0f; 
    matTexScale._m33 = 1.0f;
#endif

    return Transform(matTexScale,inPos);
}

uniform float4x4    g_skinMatrix[_MAXBONES];        ///< 128 Registers for skin bones

struct SKINVERTEX
{
    float4 P;
    float3 N;
    float3 T;
};

SKINVERTEX SkinVertex(float3 p, float3 n, float3 t, float4 indices, float4 weights)
{
    SKINVERTEX Out = (SKINVERTEX) 0;
    for(int i = 0; i < 4; i++)
    {
        Out.P.xyz += Transform(g_skinMatrix[indices.x], float4(p,1)).xyz * weights.x;
        Out.N += (float3)(Transform((float3x3) g_skinMatrix[indices.x], n) * weights.x);

        #if !defined(SH_VERSION_SH1)
        Out.T += (float3)(Transform((float3x3) g_skinMatrix[indices.x], t) * weights.x);
        #endif

        indices.xyzw = indices.yzwx;
        weights.xyzw = weights.yzwx;
    }

    Out.P.w = 1;
    Out.N = (float3)normalize(Out.N);
    
    #if !defined(SH_VERSION_SH1)
    Out.T = (float3)normalize(Out.T);
    #endif

    return Out;
}


////////////////////////////////////////////////////
// Vertex Shaders
////////////////////////////////////////////////////
float4  FocusZ  : register(c0);

float4 g_texelSize01, g_texelSize23;

void DOF_VS(float4 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC : TEXCOORD0)
{
    oPos = iPos;

    oTC = iTC;
}

float4x4    g_matWorldViewProjection, g_matWorldView;
float3x3    g_matWorld;

float4      g_kernelValues;

static float4 vFocalPlane = float4(0,0,1,1);
static float fHyperfocalDistance = 0.1f;
static float MaxBlurFactor = 3.0f / 4.0f;

void Object_VS(float4 iPos : POSITION,
#ifdef _USE_SKINMATRIX
               float4 Indices : BLENDINDICES,
               float4 Weights : BLENDWEIGHT,
#endif
               out float4 oPos : POSITION,
               out float oTC : TEXCOORD0)
{
#ifdef _USE_SKINMATRIX
    SKINVERTEX v = SkinVertex(iPos, 0, 0, Indices, Weights);
    iPos = v.P;
#endif

    oPos = Transform(g_matWorldViewProjection, iPos);

    float3 vViewPosition = Transform(g_matWorldView, iPos);
    
    vFocalPlane.w = -abs( sin( g_kernelValues.y * .1f ) ) * 70;
    
    float fBlurFactor = dot(float4(vViewPosition, 1.0), vFocalPlane) * fHyperfocalDistance;
    oTC = pow(fBlurFactor, 2);
}



////////////////////////////////////////////////////
// Pixel Shaders
////////////////////////////////////////////////////
sampler Original_Image  : register(s0);
sampler Depth_Image     : register(s1);
sampler Blur_Image      : register(s2);

float4 DOF_PS(float2 iTC : TEXCOORD0
            #if defined(_MRT1)
            ,out float4 oColor1 : COLOR1
            #endif
            #if defined(_MRT2)
            ,out float4 oColor2 : COLOR2
            #endif
            #if defined(_MRT3)
            ,out float4 oColor3 : COLOR3
            #endif
              ) : COLOR0
{
    float3 original = tex2D(Original_Image, iTC + g_texelSize01.xy * .5f);

    float d = 0;
    {
        float x = g_texelSize01.z*2;
        float y = g_texelSize01.w*2;
        d += tex2D(Depth_Image, iTC + float2(-x,-y)).r;
        d += tex2D(Depth_Image, iTC + float2(x,-y)).r;
        d += tex2D(Depth_Image, iTC + float2(-x,y)).r;
        d += tex2D(Depth_Image, iTC + float2(x,y)).r;
        
        d /= 4;
    }
    
    float3 blur = 0;
    {
        float x = g_texelSize23.x;
        float y = g_texelSize23.y;

        blur += tex2D(Blur_Image, iTC + float2(-x, -y) * 1);
        blur += tex2D(Blur_Image, iTC + float2(x, -y) * 1);
        blur += tex2D(Blur_Image, iTC + float2(-x, y) * 1);
        blur += tex2D(Blur_Image, iTC + float2(x, y) * 1);
    
        blur /= 4;
    }   
    
    return float4(original * (1-d) + blur * (d), 1);
}


float4 Object_PS(float iTC : TEXCOORD0
                #if defined(_MRT1)
                ,out float4 oColor1 : COLOR1
                #endif
                #if defined(_MRT2)
                ,out float4 oColor2 : COLOR2
                #endif
                #if defined(_MRT3)
                ,out float4 oColor3 : COLOR3
                #endif               
                 ) : COLOR0
{
    float d = iTC.x;
    return float4(d, d, d, d);
}

#ifdef _VERTEX_SHADER

#define _SHADOWMAP_CGFX

//////////////////////////////////////
// MATRIX MULTIPLICATION
//////////////////////////////////////
float3 Transform(float3x3 mat, float3 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif
}

float4 Transform(float4x4 mat, float4 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

float2 Transform(float2x2 mat, float2 v)
{
#if defined(_XENON)
    [isolate]
    {
        return mul(mat, v);
    }
#elif defined(_GCM)
    return mul(v, mat);
#else
    return mul(mat, v);
#endif

}

//this conversion will not deal with renormalizations because is a bad way to handle bad data passing to the shader.
//the main problem is that cg-compiler isn't as smart as hlsl-compiler dealing with already normalized vectors
float3x3 GetWorldToTangentMatrix(float3x3 worldmtx,float3 tangent, float3 normal)
{
    float3x3 worldToTangent = 0;
    worldToTangent[0] = normalize(Transform(worldmtx, tangent));
    worldToTangent[2] = normalize(Transform(worldmtx, normal));
    worldToTangent[1] = normalize(cross(worldToTangent[0], worldToTangent[2]));    

    return worldToTangent;
}

float4 TransformPlanarReflection(float4 inPos)
{
    float4x4    matTexScale = 0;

#if !defined(_GCM)
    matTexScale._m00 = 0.5f;
    matTexScale._m11 =  -.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m03 = 0.5f; 
    matTexScale._m13 = 0.5f;
    matTexScale._m23 = 1.0f; 
    matTexScale._m33 = 1.0f;
#else
    matTexScale._m00 = 0.5f;
    matTexScale._m11 = -0.5f;
    matTexScale._m22 = 0.0f;
    matTexScale._m30 = 0.5f; 
    matTexScale._m31 = 0.5f;
    matTexScale._m32 = 1.0f; 
    matTexScale._m33 = 1.0f;
#endif

    return Transform(matTexScale,inPos);
}

uniform float4x4    g_skinMatrix[_MAXBONES];        ///< 128 Registers for skin bones

struct SKINVERTEX
{
    float4 P;
    float3 N;
    float3 T;
};

SKINVERTEX SkinVertex(float3 p, float3 n, float3 t, float4 indices, float4 weights)
{
    SKINVERTEX Out = (SKINVERTEX) 0;
    for(int i = 0; i < 4; i++)
    {
        Out.P.xyz += Transform(g_skinMatrix[indices.x], float4(p,1)).xyz * weights.x;
        Out.N += (float3)(Transform((float3x3) g_skinMatrix[indices.x], n) * weights.x);

        #if !defined(SH_VERSION_SH1)
        Out.T += (float3)(Transform((float3x3) g_skinMatrix[indices.x], t) * weights.x);
        #endif

        indices.xyzw = indices.yzwx;
        weights.xyzw = weights.yzwx;
    }

    Out.P.w = 1;
    Out.N = (float3)normalize(Out.N);
    
    #if !defined(SH_VERSION_SH1)
    Out.T = (float3)normalize(Out.T);
    #endif

    return Out;
}


////////////////////////////////////////////////////
// Vertex Shaders
////////////////////////////////////////////////////

#ifdef _LIGHT0_POINT
    float4x4    g_matWorld;
#endif

float4x4    g_matWorldViewProjection;
float4x4    g_matTextureProjection;


void Object_VS(

                float3 inPos                : POSITION,         ///< Untransformed vertex position
                #ifdef _USE_SKINMATRIX
                    float4 inSkinIndices    : BLENDINDICES,     ///< Skin vertex indices
                    float4 inSkinWeights    : BLENDWEIGHT,      ///< Skin vertex weights
                #endif
                #ifdef _MAP_DIFFUSE
                    float2 inUV             : TEXCOORD0,        ///< Vertex uv coordinates
                #endif
               
               out float4 outHPos   : POSITION,     ///< Transformed vertex position
               out float4 outVPos   : TEXCOORD0     ///< Position of the vertex
               #ifdef _MAP_DIFFUSE
                ,out float2 outUV   : TEXCOORD1     ///< UV coordinate for albedo Albedo
               #endif
               
               )
{
    // Apply Skin to the Vertex
    #ifdef _USE_SKINMATRIX
        SKINVERTEX skin = SkinVertex(inPos.xyz,0,0, inSkinIndices, inSkinWeights);
        float4 nPos = skin.P;
    #else
        float4 nPos = float4(inPos, 1);     
    #endif

    // The matTextureProjection has the transformation (view and projection) of the light camera    
    outHPos = Transform(g_matTextureProjection, nPos);
    
    #ifdef _LIGHT0_POINT
        outVPos = Transform(g_matWorld, nPos);
    #else
        outVPos = outHPos;
    #endif

    // Copy the uv mapping, this is used to check for pixels with transparency
    #ifdef _MAP_DIFFUSE
        outUV.xy = inUV;
    #endif
}

#else // End of Vertex Shader


////////////////////////////////////////////////////
// Pixel Shaders
////////////////////////////////////////////////////

#ifdef _LIGHT0_POINT
    float4      g_lightPosition0;
#endif

#ifdef _MAP_DIFFUSE
    uniform sampler2D sDiffuse : register(s0);
#endif

float4 Object_PS(
            float4 inVertexPos : TEXCOORD0
            #ifdef _MAP_DIFFUSE
               ,float2 inVertexUV : TEXCOORD1
            #endif
            #if defined(_MRT1)
            ,out float4 oColor1 : COLOR1
            #endif
            #if defined(_MRT2)
            ,out float4 oColor2 : COLOR2
            #endif
            #if defined(_MRT3)
            ,out float4 oColor3 : COLOR3
            #endif
                ) : COLOR0
{
    float4 Out = 1;
    
    // Read the albedo texture to check for transparency
    #ifdef _MAP_DIFFUSE
        Out.a = tex2D(sDiffuse, inVertexUV.xy).a;
    #endif
    
    #ifdef _LIGHT0_DIRECTIONAL
        Out.r = inVertexPos.z;
    #endif

    #ifdef _LIGHT0_SPOT
        Out.r = inVertexPos.z / inVertexPos.w;      
    #endif

    #ifdef _LIGHT0_POINT
        Out.r = length(inVertexPos.xyz - g_lightPosition0.xyz) * g_lightPosition0.w;
    #endif

    return Out;
}

#endif



struct VSI_SCREEN
{
    float4 pos      : POSITION;
    float4 color    : COLOR0;
    float2 uv       : TEXCOORD0;
};

struct VSO_SCREEN
{
    float4 pos      : POSITION;
    float2 uv       : TEXCOORD0_centroid;
};


////////////////////////////////////////////////////
// Vertex Shaders
////////////////////////////////////////////////////
float4 g_texelSize01;
float4 g_texelSize89;

void main_VS(float4 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC : TEXCOORD0)
{
    oPos = iPos;

#ifndef _XENON
    oTC = iTC + g_texelSize89.xy * .5f;
#else
    oTC = iTC;// + g_texelSize89.xy * .5f;
#endif
}

////////////////////////////////////////////////////
// Pixel Shaders
////////////////////////////////////////////////////
sampler2D sTex          : register(s0);
sampler2D DepthTex      : register(s9);


float4 main_PS(float2 iTC : TEXCOORD0
                #if defined(_MRT1)
                ,out float4 oColor1 : COLOR1
                #endif
                #if defined(_MRT2)
                ,out float4 oColor2 : COLOR2
                #endif
                #if defined(_MRT3)
                ,out float4 oColor3 : COLOR3
                #endif
               ) : COLOR0
{
    return float4(tex2Dproj(DepthTex, float4(iTC.xy, .9, 1)).rgb, 1);
}

float4 main_copy_PS(float2 iTC : TEXCOORD0_centroid
                    #if defined(_MRT1)
                    ,out float4 oColor1 : COLOR1
                    #endif
                    #if defined(_MRT2)
                    ,out float4 oColor2 : COLOR2
                    #endif
                    #if defined(_MRT3)
                    ,out float4 oColor3 : COLOR3
                    #endif
                    ) : COLOR0
{
    return float4(tex2D(DepthTex, iTC.xy).rgb,1);
}

float4 frustum_PS(float2 iTC : TEXCOORD0
                    #if defined(_MRT1)
                    ,out float4 oColor1 : COLOR1
                    #endif
                    #if defined(_MRT2)
                    ,out float4 oColor2 : COLOR2
                    #endif
                    #if defined(_MRT3)
                    ,out float4 oColor3 : COLOR3
                    #endif
                  ) : COLOR0
{
    return float4(1,1,0,1);
}
// now this shader program has become an official 'render a whatever-you-want squad' program

float4 g_specialVector1;    // adjust factors for texture coordinates
float4 g_specialVector2;    // adjust factors for screen space position


void main_VS(float3 iPos : POSITION,
          float2 iTC : TEXCOORD0,
          out float4 oPos : POSITION,
          out float2 oTC : TEXCOORD0)
{
    oPos = float4(  iPos.x * g_specialVector2.x + g_specialVector2.y, 
                    iPos.y * g_specialVector2.z + g_specialVector2.w, 
                    iPos.z, 
                    1.f
                    );
    
    oTC = float2(   iTC.x * g_specialVector1.x + g_specialVector1.y, 
                    iTC.y * g_specialVector1.z + g_specialVector1.w
                    );
}


sampler2D tex   : register(s0);


float4 main_PS( float2 tc : TEXCOORD0
                #if defined(_MRT1)
                ,out float4 oColor1 : COLOR1
                #endif
                #if defined(_MRT2)
                ,out float4 oColor2 : COLOR2
                #endif
                #if defined(_MRT3)
                ,out float4 oColor3 : COLOR3
                #endif
               ) : COLOR
{
    //return float4(tex2D(tex, tc).xyz, 1.f);
    return tex2D(tex, tc);
}