/** this file is only used if you #define USE_EXTERNAL_SHADER when AssimpRenderer is compiled.
* Place it in the root dir of your application.
*/

float4x4 WorldViewProjection	: WORLDVIEWPROJECTION;
float4x4 World					: WORLD;					// die semantics kann man hier auch weglassen (ausprobiert), wozu sind die gut ?
float4x3 WorldInverseTranspose	: WORLDINVERSETRANSPOSE;

#ifndef AV_DISABLESSS
float4x3 ViewProj;
float4x3 InvViewProj;
#endif

float4 DIFFUSE_COLOR;
float4 SPECULAR_COLOR;
float4 AMBIENT_COLOR;
float4 EMISSIVE_COLOR;

#ifdef AV_SPECULAR_COMPONENT
float SPECULARITY;
float SPECULAR_STRENGTH;
#endif

#ifdef AV_OPACITY
float TRANSPARENCY;
#endif

float4 afLightColor[5];
float4 afLightColorAmbient[5];
float3 afLightDir[5];
float3 vCameraPos : CAMERAPOSITION;

#ifdef AV_SKINNING 
float4x3 gBoneMatrix[60]; 
#endif // AV_SKINNING 

#ifdef AV_DIFFUSE_TEXTURE
texture DIFFUSE_TEXTURE;
sampler DIFFUSE_SAMPLER
{
    Texture = <DIFFUSE_TEXTURE>;
    #ifdef AV_WRAPU
    AddressU = WRAP;
    #endif

    #ifdef AV_MIRRORU
    AddressU = MIRROR;
    #endif

    #ifdef AV_CLAMPU
    AddressU = CLAMP;
    #endif

    #ifdef AV_WRAPV
    AddressV = WRAP;
    #endif

    #ifdef AV_MIRRORV
    AddressV = MIRROR;
    #endif

    #ifdef AV_CLAMPV
    AddressV = CLAMP;
    #endif

    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};

#endif // AV_DIFFUSE_TEXTUR


#ifdef AV_DIFFUSE_TEXTURE2
texture DIFFUSE_TEXTURE2;
sampler DIFFUSE_SAMPLER2
{
    Texture = <DIFFUSE_TEXTURE2>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_DIFFUSE_TEXTUR2

#ifdef AV_SPECULAR_TEXTURE
texture SPECULAR_TEXTURE;
sampler SPECULAR_SAMPLER
{
    Texture = <SPECULAR_TEXTURE>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_SPECULAR_TEXTUR

#ifdef AV_AMBIENT_TEXTURE
texture AMBIENT_TEXTURE;
sampler AMBIENT_SAMPLER
{
    Texture = <AMBIENT_TEXTURE>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_AMBIENT_TEXTUR

#ifdef AV_OPACITY_TEXTURE
texture OPACITY_TEXTURE;
sampler OPACITY_SAMPLER
{
    Texture = <OPACITY_TEXTURE>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_OPACITY_TEXTURE

#ifdef AV_EMISSIVE_TEXTURE
texture EMISSIVE_TEXTURE;
sampler EMISSIVE_SAMPLER
{
    Texture = <EMISSIVE_TEXTURE>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_EMISSIVE_TEXTUR

#ifdef AV_NORMAL_TEXTURE
texture NORMAL_TEXTURE;
sampler NORMAL_SAMPLER
{
    Texture = <NORMAL_TEXTURE>;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    MipFilter=LINEAR;
};
#endif // AV_NORMAL_TEXTURE

#ifdef AV_SKYBOX_LOOKUP
textureCUBE lw_tex_envmap;
samplerCUBE EnvironmentMapSampler = sampler_state
{
    Texture = (lw_tex_envmap);
    AddressU = CLAMP;
    AddressV = CLAMP;
    AddressW = CLAMP;
    MAGFILTER = linear;
    MINFILTER = linear;
};
#endif // AV_SKYBOX_LOOKUP

struct VS_INPUT
{
    float3 Position : POSITION;
    float3 Normal : NORMAL;
    float4 Color : COLOR0;
    float3 Tangent   : TANGENT;
    float3 Bitangent : BINORMAL;
    float2 TexCoord0 : TEXCOORD0;

    #ifdef AV_DIFFUSE_TEXTURE2 
    float2 TexCoord1 : TEXCOORD1;
    #endif 

    #ifdef AV_SKINNING 
    float4 BlendIndices : BLENDINDICES;
    float4 BlendWeights : BLENDWEIGHT;
    #endif // AV_SKINNING 
};

struct VS_OUTPUT
{
    float4 Position : POSITION;
    float3 ViewDir : TEXCOORD0;
    float4 Color : COLOR0;
    #ifndef AV_NORMAL_TEXTURE
    float3 Normal  : TEXCOORD1;
    #endif
    float2 TexCoord0 : TEXCOORD2;
    #ifdef AV_DIFFUSE_TEXTURE2 
    float2 TexCoord1 : TEXCOORD3;
    #endif 
    #ifdef AV_NORMAL_TEXTURE
    float3 Light0 : TEXCOORD3;
    float3 Light1 : TEXCOORD4;
    #endif
};

struct VS_OUTPUT_FF
{
    float4 Position : POSITION;
    float4 DiffuseColor : COLOR0;
    float4 SpecularColor : COLOR1;
    float2 TexCoord0 : TEXCOORD0;
};

#ifndef AV_SKYBOX_LOOKUP
#define AV_DISABLESSS
#endif

#ifndef AV_DISABLESSS
float3 GetSSSCubeMap(float3 Reflect)
{
    float3 ScreenReflect = mul(Reflect,ViewProj);
    float3 fDX = ddx(ScreenReflect);
    float3 fDY = ddy(ScreenReflect);
    float3 fColor = texCUBE(EnvironmentMapSampler,Reflect).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f * 2.0 / 3.5) * fDX + (0.4f * 2.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f * 3.0 / 3.5) * fDX + (0.4f *-1.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f * 1.0 / 3.5) * fDX + (0.4f *-3.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f *-2.0 / 3.5) * fDX + (0.4f *-2.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f *-3.0 / 3.5) * fDX + (0.4f * 1.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor += texCUBEgrad(EnvironmentMapSampler,mul( ScreenReflect + (0.4f *-1.0 / 3.5) * fDX + (0.4f * 3.0 / 3.5) * fDY, InvViewProj),fDX,fDY).rgb;
    fColor /= 7;
    return fColor;
}
#else
#define GetSSSCubeMap(_refl) (texCUBElod(EnvironmentMapSampler,float4(_refl,0.0f)).rgb) 
#endif

#ifdef AV_NORMAL_TEXTURE
#undef GetSSSCubeMap
#define GetSSSCubeMap(_refl) (float3(1.0f,1.0f,1.0f))
#endif

VS_OUTPUT MaterialVShader_D1(VS_INPUT IN)
{
    VS_OUTPUT Out = (VS_OUTPUT)0;

    #ifdef AV_SKINNING 
    float4 weights = IN.BlendWeights; 
    weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); 
    float4 localPos = float4( IN.Position, 1.0f); 
    float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; 
    #else 
    float3 objPos = IN.Position; 
    #endif // AV_SKINNING 

    Out.Position = mul( float4( objPos, 1.0f), WorldViewProjection);
    float3 WorldPos = mul( float4( objPos, 1.0f), World);
    Out.TexCoord0 = IN.TexCoord0;

    #ifdef AV_DIFFUSE_TEXTURE2 
    Out.TexCoord1 = IN.TexCoord1;
    #endif
    
    Out.Color = IN.Color;
    
    #ifndef AV_NORMAL_TEXTURE
    Out.ViewDir = vCameraPos - WorldPos;
    Out.Normal = mul(IN.Normal, World);				// PNX: war:  = mul(IN.Normal, WorldInverseTranspose);
    #endif

    #ifdef AV_NORMAL_TEXTURE
    float3x3 TBNMatrix = float3x3(IN.Tangent, IN.Bitangent, IN.Normal);
    float3x3 WTTS      = mul(TBNMatrix, (float3x3)WorldInverseTranspose);
    Out.Light0         = normalize(mul(WTTS, afLightDir[0] ));
    Out.ViewDir = normalize(mul(WTTS, (vCameraPos - WorldPos)));
    #endif

    return Out;
}

VS_OUTPUT MaterialVShader_D2(VS_INPUT IN)
{
    VS_OUTPUT Out = (VS_OUTPUT)0;

    #ifdef AV_SKINNING 
    float4 weights = IN.BlendWeights; 
    weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); 
    float4 localPos = float4( IN.Position, 1.0f); 
    float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; 
    #else 
    float3 objPos = IN.Position; 
    #endif // AV_SKINNING 

    Out.Position = mul( float4( objPos, 1.0f), WorldViewProjection);
    float3 WorldPos = mul( float4( objPos, 1.0f), World);
    Out.TexCoord0 = IN.TexCoord0;

    #ifdef AV_DIFFUSE_TEXTURE2 
    Out.TexCoord1 = IN.TexCoord1;
    #endif

    Out.Color = IN.Color;

    #ifndef AV_NORMAL_TEXTURE
    Out.ViewDir = vCameraPos - WorldPos;	
    Out.Normal = mul(IN.Normal, World);				// PNX: war:  = mul(IN.Normal, WorldInverseTranspose);
    #endif

    #ifdef AV_NORMAL_TEXTURE
    float3x3 TBNMatrix = float3x3(IN.Tangent, IN.Bitangent, IN.Normal);
    float3x3 WTTS      = mul(TBNMatrix, (float3x3)WorldInverseTranspose);
    Out.Light0         = normalize(mul(WTTS, afLightDir[0] ));
    Out.Light1         = normalize(mul(WTTS, afLightDir[1] ));
    Out.ViewDir = normalize(mul(WTTS, (vCameraPos - WorldPos)));
    #endif

    return Out;
}

VS_OUTPUT_FF MaterialVShader_FF(VS_INPUT IN)
{
    VS_OUTPUT_FF Out = (VS_OUTPUT_FF)0;

    #ifdef AV_SKINNING 
    float4 weights = IN.BlendWeights; 
    weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); 
    float4 localPos = float4( IN.Position, 1.0f); 
    float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; 
    objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; 
    #else 
    float3 objPos = IN.Position; 
    #endif // AV_SKINNING 

    Out.Position = mul( float4( objPos, 1.0f), WorldViewProjection);
    float3 worldPos = mul( float4( objPos, 1.0f), World);
    float3 worldNormal = normalize( mul( IN.Normal, (float3x3) WorldInverseTranspose)); 
    Out.TexCoord0 = IN.TexCoord0;
    float4 diffuseColor = float4( 0.0f, 0.0f, 0.0f, 1.0f); 
    for( int a = 0; a < 2; a++) 
      diffuseColor.rgb += saturate( dot( afLightDir[a], worldNormal)) * afLightColor[a].rgb; 

    Out.DiffuseColor = diffuseColor * DIFFUSE_COLOR + float4( 0.2f, 0.2f, 0.2f, 1.0f) * AMBIENT_COLOR; ; 
    float4 specularColor = float4( 0.0f, 0.0f, 0.0f, 1.0f); 
    
    #ifdef AV_SPECULAR_COMPONENT
    float3 viewDir = normalize( worldPos - vCameraPos); 
    for( int a = 0; a < 2; a++) 
    { 
      float3 reflDir = reflect( afLightDir[a], worldNormal); 
      float specIntensity = pow( saturate( dot( reflDir, viewDir)), SPECULARITY) * SPECULAR_STRENGTH; 
      specularColor.rgb += afLightColor[a] * specIntensity; 
    } 
    #endif // AV_SPECULAR_COMPONENT

    Out.SpecularColor = specularColor * SPECULAR_COLOR + EMISSIVE_COLOR; 
    return Out;
}

float4 MaterialPShaderSpecular_D1(VS_OUTPUT IN) : COLOR
{
    float4 OUT = float4(0.0f,0.0f,0.0f,1.0f);

    #ifdef AV_NORMAL_TEXTURE
    float3 IN_Light0 = normalize(IN.Light0);
    float3 Normal  =  normalize(2.0f * tex2D(NORMAL_SAMPLER, IN.TexCoord0).rgb - 1.0f);
    #else
    float3 Normal = normalize(IN.Normal);
    #endif 

    float3 ViewDir = normalize(IN.ViewDir);

    #ifdef AV_SPECULAR_COMPONENT
    float3 Reflect = -normalize(reflect (ViewDir,Normal));
    #endif // !AV_SPECULAR_COMPONENT

    {
        #ifdef AV_NORMAL_TEXTURE
            float L1 =  dot(Normal,IN_Light0) * 0.5f + 0.5f;
            #define AV_LIGHT_0 IN_Light0
        #else
            float L1 = dot(Normal,afLightDir[0]) * 0.5f + 0.5f;				// PNX: war: float L1 = dot(Normal,afLightDir[0]) * 0.5f + 0.5f;
            #define AV_LIGHT_0 afLightDir[0]
        #endif

        #ifdef AV_DIFFUSE_TEXTURE2
            float fHalfLambert = 1.f;
        #else
            float fHalfLambert = L1*L1;
        #endif 

        #ifdef AV_DIFFUSE_TEXTURE
            OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * fHalfLambert * IN.Color.rgb +
        #else
            OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * fHalfLambert * IN.Color.rgb +
        #endif // !AV_DIFFUSE_TEXTURE

        #ifdef AV_SPECULAR_COMPONENT
            #ifndef AV_SKYBOX_LOOKUP
                #ifdef AV_SPECULAR_TEXTURE
                SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
                #else
                SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
                #endif // !AV_SPECULAR_TEXTURE
            #else
                #ifdef AV_SPECULAR_TEXTURE
                SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
                #else
                SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
                #endif // !AV_SPECULAR_TEXTURE
            #endif // !AV_SKYBOX_LOOKUP
        #endif // !AV_SPECULAR_COMPONENT

        #ifdef AV_AMBIENT_TEXTURE
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb +
        #else
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb + 
        #endif // !AV_AMBIENT_TEXTURE

        #ifdef AV_EMISSIVE_TEXTURE
        EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
        EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE

        #ifdef AV_DIFFUSE_TEXTURE2
        OUT.rgb *= tex2D(DIFFUSE_SAMPLER2,IN.TexCoord1).rgb*4.0f;
        #endif 
    }
    #ifdef AV_OPACITY
    OUT.a = TRANSPARENCY;
    #endif

    #ifdef AV_OPACITY_TEXTURE
    OUT.a *= tex2D(OPACITY_SAMPLER,IN.TexCoord0). AV_OPACITY_TEXTURE_REGISTER_MASK;
    #endif
    return OUT;
    #undef AV_LIGHT_0
}

float4 MaterialPShaderSpecular_D2(VS_OUTPUT IN) : COLOR
{
    float4 OUT = float4(0.0f,0.0f,0.0f,1.0f);
    #ifdef AV_NORMAL_TEXTURE
    float3 IN_Light0 = normalize(IN.Light0);
    float3 IN_Light1 = normalize(IN.Light1);
    float3 Normal  =  normalize(2.0f * tex2D(NORMAL_SAMPLER, IN.TexCoord0).rgb - 1.0f);
    #else
    float3 Normal = normalize(IN.Normal);
    #endif 
    float3 ViewDir = normalize(IN.ViewDir);
    #ifdef AV_SPECULAR_COMPONENT
    float3 Reflect = -normalize(reflect (ViewDir,Normal));
    #endif // !AV_SPECULAR_COMPONENT
    {
        #ifdef AV_NORMAL_TEXTURE
        float L1 = dot(Normal,IN_Light0) * 0.5f + 0.5f;
        #define AV_LIGHT_0 IN_Light0
        #else
        float L1 = dot(Normal,afLightDir[0]) * 0.5f + 0.5f;
        #define AV_LIGHT_0 afLightDir[0]
        #endif
        float fHalfLambert = L1*L1;
        #ifdef AV_DIFFUSE_TEXTURE
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * fHalfLambert  * IN.Color.rgb +
        #else
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * fHalfLambert  * IN.Color.rgb +
        #endif // !AV_DIFFUSE_TEXTURE
        #ifdef AV_SPECULAR_COMPONENT
        #ifndef AV_SKYBOX_LOOKUP
        #ifdef AV_SPECULAR_TEXTURE
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
        #else
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
        #endif // !AV_SPECULAR_TEXTURE
        #else
        #ifdef AV_SPECULAR_TEXTURE
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
        #else
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + 
        #endif // !AV_SPECULAR_TEXTURE
        #endif // !AV_SKYBOX_LOOKUP
        #endif // !AV_SPECULAR_COMPONENT
        #ifdef AV_AMBIENT_TEXTURE
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb + 
        #else
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb + 
        #endif // !AV_AMBIENT_TEXTURE
        #ifdef AV_EMISSIVE_TEXTURE
        EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
        EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE
    }
    {
        #ifdef AV_NORMAL_TEXTURE
        float L1 = dot(Normal,IN_Light1) * 0.5f + 0.5f;
        #define AV_LIGHT_1 IN_Light1
        #else
        float L1 = dot(Normal,afLightDir[1]) * 0.5f + 0.5f;
        #define AV_LIGHT_1 afLightDir[1]
        #endif

        float fHalfLambert = L1*L1;

        #ifdef AV_DIFFUSE_TEXTURE
        OUT.rgb += afLightColor[1].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * fHalfLambert  * IN.Color.rgb +
        #else
        OUT.rgb += afLightColor[1].rgb * DIFFUSE_COLOR.rgb * fHalfLambert   * IN.Color.rgb +
        #endif // !AV_DIFFUSE_TEXTURE

        #ifdef AV_SPECULAR_COMPONENT
            #ifndef AV_SKYBOX_LOOKUP
                #ifdef AV_SPECULAR_TEXTURE
                    SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + 
                #else
                    SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + 
                #endif // !AV_SPECULAR_TEXTURE
            #else
                #ifdef AV_SPECULAR_TEXTURE
                    SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + 
                #else
                    SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + 
                #endif // !AV_SPECULAR_TEXTURE
            #endif // !AV_SKYBOX_LOOKUP
        #endif // !AV_SPECULAR_COMPONENT

        #ifdef AV_AMBIENT_TEXTURE
            AMBIENT_COLOR.rgb * afLightColorAmbient[1].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb + 
        #else
            AMBIENT_COLOR.rgb * afLightColorAmbient[1].rgb + 
        #endif // !AV_AMBIENT_TEXTURE

        #ifdef AV_EMISSIVE_TEXTURE
            EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
            EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE
    }
    #ifdef AV_OPACITY
    OUT.a = TRANSPARENCY;
    #endif

    #ifdef AV_OPACITY_TEXTURE
    OUT.a *= tex2D(OPACITY_SAMPLER,IN.TexCoord0). AV_OPACITY_TEXTURE_REGISTER_MASK;
    #endif

    return OUT;
    #undef AV_LIGHT_0
    #undef AV_LIGHT_1
}


float4 MaterialPShaderSpecular_PS20_D1(VS_OUTPUT IN) : COLOR
{
    float4 OUT = float4(0.0f,0.0f,0.0f,1.0f);
    #ifdef AV_NORMAL_TEXTURE
    float3 IN_Light0 = normalize(IN.Light0);
    float3 Normal  =  normalize(2.0f * tex2D(NORMAL_SAMPLER, IN.TexCoord0).rgb - 1.0f);
    #else
    float3 Normal = normalize(IN.Normal);
    #endif 
    float3 ViewDir = normalize(IN.ViewDir);
    {
        #ifdef AV_NORMAL_TEXTURE
        float L1 = dot(Normal,IN_Light0) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,IN_Light0);
        #else
        float L1 = dot(Normal,afLightDir[0]) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,afLightDir[0]);
        #endif
        #ifdef AV_DIFFUSE_TEXTURE
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * L1 +
        #else
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * L1 +
        #endif // !AV_DIFFUSE_TEXTURE
        #ifdef AV_SPECULAR_COMPONENT
        #ifdef AV_SPECULAR_TEXTURE
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #else
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #endif // !AV_SPECULAR_TEXTURE
        #endif // !AV_SPECULAR_COMPONENT
        #ifdef AV_AMBIENT_TEXTURE
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb +
        #else
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb +
        #endif // !AV_AMBIENT_TEXTURE
        #ifdef AV_EMISSIVE_TEXTURE
        EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
        EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE
    }

    #ifdef AV_OPACITY
    OUT.a = TRANSPARENCY;
    #endif

    #ifdef AV_OPACITY_TEXTURE
    OUT.a *= tex2D(OPACITY_SAMPLER,IN.TexCoord0). AV_OPACITY_TEXTURE_REGISTER_MASK;
    #endif

    return OUT;
}

float4 MaterialPShaderSpecular_PS20_D2(VS_OUTPUT IN) : COLOR
{
    float4 OUT = float4(0.0f,0.0f,0.0f,1.0f);
    #ifdef AV_NORMAL_TEXTURE
    float3 IN_Light0 = normalize(IN.Light0);
    float3 IN_Light1 = normalize(IN.Light1);
    float3 Normal  =  normalize(2.0f * tex2D(NORMAL_SAMPLER, IN.TexCoord0) - 1.0f);
    #else
    float3 Normal = normalize(IN.Normal);
    #endif 
    float3 ViewDir = normalize(IN.ViewDir);
    {
        #ifdef AV_NORMAL_TEXTURE
        float L1 = dot(Normal,IN_Light0) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,IN_Light0);
        #else
        float L1 = dot(Normal,afLightDir[0]) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,afLightDir[0]);
        #endif
        #ifdef AV_DIFFUSE_TEXTURE
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * L1 +
        #else
        OUT.rgb += afLightColor[0].rgb * DIFFUSE_COLOR.rgb * L1 +
        #endif // !AV_DIFFUSE_TEXTURE
        #ifdef AV_SPECULAR_COMPONENT
        #ifdef AV_SPECULAR_TEXTURE
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #else
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #endif // !AV_SPECULAR_TEXTURE
        #endif // !AV_SPECULAR_COMPONENT
        #ifdef AV_AMBIENT_TEXTURE
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb +
        #else
        AMBIENT_COLOR.rgb * afLightColorAmbient[0].rgb +
        #endif // !AV_AMBIENT_TEXTURE
        #ifdef AV_EMISSIVE_TEXTURE
        EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
        EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE
    }
    {
        #ifdef AV_NORMAL_TEXTURE
        float L1 = dot(Normal,IN_Light1) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,IN_Light1);
        #else
        float L1 = dot(Normal,afLightDir[1]) * 0.5f + 0.5f;
        float3 Reflect = reflect (Normal,afLightDir[1]);
        #endif
        #ifdef AV_DIFFUSE_TEXTURE
        OUT.rgb += afLightColor[1].rgb * DIFFUSE_COLOR.rgb * tex2D(DIFFUSE_SAMPLER,IN.TexCoord0).rgb * L1 +
        #else
        OUT.rgb += afLightColor[1].rgb * DIFFUSE_COLOR.rgb * L1 +
        #endif // !AV_DIFFUSE_TEXTURE
        #ifdef AV_SPECULAR_COMPONENT
        #ifdef AV_SPECULAR_TEXTURE
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #else
        SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + 
        #endif // !AV_SPECULAR_TEXTURE
        #endif // !AV_SPECULAR_COMPONENT
        #ifdef AV_AMBIENT_TEXTURE
        AMBIENT_COLOR.rgb * afLightColorAmbient[1].rgb * tex2D(AMBIENT_SAMPLER,IN.TexCoord0).rgb +
        #else
        AMBIENT_COLOR.rgb * afLightColorAmbient[1].rgb + 
        #endif // !AV_AMBIENT_TEXTURE
        #ifdef AV_EMISSIVE_TEXTURE
        EMISSIVE_COLOR.rgb * tex2D(EMISSIVE_SAMPLER,IN.TexCoord0).rgb;
        #else 
        EMISSIVE_COLOR.rgb;
        #endif // !AV_EMISSIVE_TEXTURE
    }
    #ifdef AV_OPACITY
    OUT.a = TRANSPARENCY;
    #endif
    #ifdef AV_OPACITY_TEXTURE
    OUT.a *= tex2D(OPACITY_SAMPLER,IN.TexCoord0). AV_OPACITY_TEXTURE_REGISTER_MASK;
    #endif
    return OUT;
}


technique MaterialFXSpecular_D1
{
    pass p0
    {
        CullMode=none;

        #ifdef AV_OPACITY_TEXTURE
            AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
            DestBlend = invsrcalpha;
        #else
            #ifdef AV_OPACITY
                AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
                DestBlend = invsrcalpha;
            #endif 
        #endif

        PixelShader = compile ps_3_0 MaterialPShaderSpecular_D1();
        VertexShader = compile vs_3_0 MaterialVShader_D1();
    }
};



technique MaterialFXSpecular_D2
{
    pass p0
    {
        CullMode=none;
        #ifdef AV_OPACITY_TEXTURE
            AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
            DestBlend = invsrcalpha;
        #else
            #ifdef AV_OPACITY
                AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
                DestBlend = invsrcalpha;
            #endif 
        #endif

        PixelShader = compile ps_3_0 MaterialPShaderSpecular_D2();
        VertexShader = compile vs_3_0 MaterialVShader_D2();
    }
};


technique MaterialFXSpecular_PS20_D1
{
    pass p0
    {
        CullMode=none;

        #ifdef AV_OPACITY_TEXTURE
            AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
            DestBlend = invsrcalpha;
        #else
            #ifdef AV_OPACITY
                AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
                DestBlend = invsrcalpha;
            #endif 
        #endif

        PixelShader = compile ps_2_0 MaterialPShaderSpecular_PS20_D1();
        VertexShader = compile vs_2_0 MaterialVShader_D1();
    }
};


technique MaterialFXSpecular_PS20_D2
{
    pass p0
    {
        CullMode=none;

        #ifdef AV_OPACITY_TEXTURE
            AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
            DestBlend = invsrcalpha;
        #else
            #ifdef AV_OPACITY
                AlphaBlendEnable=TRUE;SrcBlend = srcalpha;
                DestBlend = invsrcalpha;
            #endif 
        #endif
        PixelShader = compile ps_2_0 MaterialPShaderSpecular_PS20_D2();
        VertexShader = compile vs_2_0 MaterialVShader_D2();
    }
};



technique MaterialFX_FF
{
    pass p0
    {
        CullMode=none;
        SpecularEnable = true; 
        VertexShader = compile vs_2_0 MaterialVShader_FF();
        ColorOp[0] = Modulate;
        ColorArg0[0] = Texture;
        ColorArg1[0] = Diffuse;
        AlphaOp[0] = Modulate;
        AlphaArg0[0] = Texture;
        AlphaArg1[0] = Diffuse;
    }
};
