#ifndef BONECOUNT
    #define BONECOUNT 20
#endif

#ifdef _X360
    #define boneid1 int
    #define boneid2 int2
    #define boneid3 int3
    #define boneid4 int4
#else
    #define boneid1 float
    #define boneid2 float2
    #define boneid3 float3
    #define boneid4 float4
#endif

#ifdef BONEMODE_4x3
	float4 bones[BONECOUNT*3] : Bones4x3;
#endif

#ifdef BONEMODE_4x4
	float4 bones[BONECOUNT*4] : Bones4x4;
#endif

#ifdef BONEMODE_Array
	float4x4 bones[BONECOUNT] : World;
#endif

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

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

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


boneid4 VS_ScaleBoneIDsFromD3DCOLOR(boneid4 id)
{
#ifdef _X360
    #ifdef BONEMODE_4x3
        id *= 3;
    #endif
    #ifdef BONEMODE_4x4
        id *= 4;
    #endif
        
    return id.yzwx; // Convert ARGB layout of data (on PC it's D3DCOLOR, not UBYTE4) to normal
#else
    #ifdef BONEMODE_4x4
        return id * 1020.1;
    #endif
    #ifdef BONEMODE_4x3
        return id * 765.1;
    #endif
    #ifdef BONEMODE_Array
        return id * 255.1;
    #endif
#endif
}

boneid1 VS_ScaleBatchID(boneid1 id)
{
#ifdef BONEMODE_4x3
    id *= 3;
#endif
#ifdef BONEMODE_4x4
    id *= 4;
#endif
    return id;
}

#ifdef BONEMODE_4x4
    float4x4 GetBoneMat(boneid1 boneid)
    {
	    return transpose(float4x4(bones[boneid], bones[boneid+1], bones[boneid+2], bones[boneid+3]));
    }
#endif

#ifdef BONEMODE_4x3
    #ifdef _X360
        #ifdef _USEBROKEN4x3
            float4x3 GetBoneMat(boneid1 boneid)
            {
	            return transpose(float3x4(bones[boneid], bones[boneid+1], bones[boneid+2]));
            }
        #else
            float4x4 GetBoneMat(boneid1 boneid)
            {
	            return transpose(float4x4(bones[boneid], bones[boneid+1], bones[boneid+2], float4(0,0,0,1)));
            }
        #endif
    #else
        float4x3 GetBoneMat(boneid1 boneid)
        {
	        return transpose(float3x4(bones[boneid], bones[boneid+1], bones[boneid+2]));
        }
    #endif
#endif

#ifdef BONEMODE_Array
    float4x4 GetBoneMat(boneid1 boneid)
    {
	    return bones[boneid];
    }
#endif

void VS_TransformBonesP_1(float4 pos, out float4 posout, boneid1 boneid, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
}

void VS_TransformBonesP_1_NoWorld(float4 pos, out float4 posout, boneid1 boneid)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    posout.w = pos.w;
}


void VS_TransformBonesP_2(float4 pos, out float4 posout, boneid2 boneids, float2 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );    
}

void VS_TransformBonesP_2_NoWorld(float4 pos, out float4 posout, boneid2 boneids, float2 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
}


void VS_TransformBonesP_3(float4 pos, out float4 posout, boneid3 boneids, float3 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );    
}

void VS_TransformBonesP_3_NoWorld(float4 pos, out float4 posout, boneid3 boneids, float3 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
}


void VS_TransformBonesP_4(float4 pos, out float4 posout, boneid4 boneids, float4 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );    
}

void VS_TransformBonesP_4_NoWorld(float4 pos, out float4 posout, boneid4 boneids, float4 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
}


void VS_TransformBonesPN_1(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid1 boneid, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    normout = mul(norm, GetBoneMat(boneid));
    posout.w = pos.w;
    posout.xyz = mul( posout, world );   
    normout = mul( normout, world ); 
}

void VS_TransformBonesPN_1_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid1 boneid)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    normout = mul(norm, GetBoneMat(boneid));
    posout.w = pos.w;
}


void VS_TransformBonesPN_2(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid2 boneids, float2 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
    normout = mul( normout, world );
}

void VS_TransformBonesPN_2_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid2 boneids, float2 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
}


void VS_TransformBonesPN_3(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid3 boneids, float3 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
    normout = mul( normout, world );
}

void VS_TransformBonesPN_3_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid3 boneids, float3 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
}

void VS_TransformBonesPN_4(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid4 boneids, float4 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    normout += mul(norm, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
    normout = mul( normout, world );
}

void VS_TransformBonesPN_4_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, boneid4 boneids, float4 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    normout += mul(norm, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
}


void VS_TransformBonesPNT_1(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid1 boneid, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    normout = mul(norm, GetBoneMat(boneid));
    tangout = mul(tang, GetBoneMat(boneid));
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
    normout = mul( normout, world );
    tangout = mul( tangout, world );
}

void VS_TransformBonesPNT_1_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid1 boneid)
{
    posout.xyz = mul(pos, GetBoneMat(boneid));
    normout = mul(norm, GetBoneMat(boneid));
    tangout = mul(tang, GetBoneMat(boneid));
    posout.w = pos.w;
}


void VS_TransformBonesPNT_2(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid2 boneids, float2 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );    
    normout = mul( normout, world );
    tangout = mul( tangout, world );
}

void VS_TransformBonesPNT_2_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid2 boneids, float2 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    posout.w = pos.w;
}


void VS_TransformBonesPNT_3(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid3 boneids, float3 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    tangout += mul(tang, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );    
    normout = mul( normout, world );
    tangout = mul( tangout, world );
}

void VS_TransformBonesPNT_3_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid3 boneids, float3 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    tangout += mul(tang, GetBoneMat(boneids.z)) * boneweights.z;
    posout.w = pos.w;
}


void VS_TransformBonesPNT_4(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid4 boneids, float4 boneweights, float4x3 world)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    normout += mul(norm, GetBoneMat(boneids.w)) * boneweights.w;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    tangout += mul(tang, GetBoneMat(boneids.z)) * boneweights.z;
    tangout += mul(tang, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
    posout.xyz = mul( posout, world );
    normout = mul( normout, world );
    tangout = mul( tangout, world );
}

void VS_TransformBonesPNT_4_NoWorld(float4 pos, out float4 posout, float3 norm, out float3 normout, float3 tang, out float3 tangout, boneid4 boneids, float4 boneweights)
{
    posout.xyz = mul(pos, GetBoneMat(boneids.x)) * boneweights.x;
    posout.xyz += mul(pos, GetBoneMat(boneids.y)) * boneweights.y;
    posout.xyz += mul(pos, GetBoneMat(boneids.z)) * boneweights.z;
    posout.xyz += mul(pos, GetBoneMat(boneids.w)) * boneweights.w;
    normout = mul(norm, GetBoneMat(boneids.x)) * boneweights.x;
    normout += mul(norm, GetBoneMat(boneids.y)) * boneweights.y;
    normout += mul(norm, GetBoneMat(boneids.z)) * boneweights.z;
    normout += mul(norm, GetBoneMat(boneids.w)) * boneweights.w;
    tangout = mul(tang, GetBoneMat(boneids.x)) * boneweights.x;
    tangout += mul(tang, GetBoneMat(boneids.y)) * boneweights.y;
    tangout += mul(tang, GetBoneMat(boneids.z)) * boneweights.z;
    tangout += mul(tang, GetBoneMat(boneids.w)) * boneweights.w;
    posout.w = pos.w;
}


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

float4 WorkingLit(float LdN, float HdN, float power)
{
    return saturate(lit(LdN, HdN, power));
}

// Calculates diffuse lighting for a directional light, including the light color
void PS_DirLightD(DirectionalLight dl, float3 normalWorld, out float3 d)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, 0.0f, 0.0f);    
    d = dl.Diffuse.xyz * vLit.y;
}

// Calculates diffuse and specular lighting for a directional light, including the light colors
void PS_DirLightDS(DirectionalLight dl, float3 normalWorld, out float3 d, float power, float3 eyeVecW, out float3 s)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float3 halfVec = normalize((-dl.Direction.xyz + normalize(eyeVecW.xyz)));
    float HdN = dot(halfVec.xyz, normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, HdN, power);    
    d = dl.Diffuse.xyz * vLit.y;
    s = dl.Specular.xyz * vLit.z * vLit.y;
}

// Calculates specular lighting for a directional light, including the light colors
void PS_DirLightS(DirectionalLight dl, float3 normalWorld, float power, float3 eyeVecW, out float3 s)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float3 halfVec = normalize((-dl.Direction.xyz + normalize(eyeVecW.xyz)));
    float HdN = dot(halfVec.xyz, normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, HdN, power);    
    s = dl.Specular.xyz * vLit.z * vLit.y;
}

// Calculates diffuse lighting for a directional light, including the light color
void PS_AddDirLightD(DirectionalLight dl, float3 normalWorld, inout float3 d)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, 0.0f, 0.0f);    
    d += dl.Diffuse.xyz * vLit.y;
}

// Calculates diffuse and specular lighting for a directional light, including the light colors
void PS_AddDirLightDS(DirectionalLight dl, float3 normalWorld, inout float3 d, float power, float3 eyeVecW, inout float3 s)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float3 halfVec = normalize((-dl.Direction.xyz + normalize(eyeVecW.xyz)));
    float HdN = dot(halfVec.xyz, normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, HdN, power);    
    d += dl.Diffuse.xyz * vLit.y;
    s += dl.Specular.xyz * vLit.z * vLit.y;
}

// Calculates diffuse and specular lighting for a directional light, including the light colors
void PS_AddShadowDirLightDS(DirectionalLight dl, float3 normalWorld, inout float3 d, float power, float3 eyeVecW, inout float3 s, float islit )
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float3 halfVec = normalize((-dl.Direction.xyz + normalize(eyeVecW.xyz)));
    float HdN = dot(halfVec.xyz, normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, HdN, power) * islit;    
    d += dl.Diffuse.xyz * vLit.y;
    s += dl.Specular.xyz * vLit.z * vLit.y;
}

// Calculates specular lighting for a directional light, including the light colors
void PS_AddDirLightS(DirectionalLight dl, float3 normalWorld, float power, float3 eyeVecW, inout float3 s)
{
    float LdN = dot(dl.Direction.xyz, -normalWorld.xyz);
    float3 halfVec = normalize((-dl.Direction.xyz + normalize(eyeVecW.xyz)));
    float HdN = dot(halfVec.xyz, normalWorld.xyz);
    float4 vLit = WorkingLit(LdN, HdN, power);    
    s += dl.Specular.xyz * vLit.z * vLit.y;
}


// Calculates diffuse lighting for a point light, including light color
void PS_PointLightD(PointLight pl, float3 normalWorld, float3 vertPosWorld, out float3 d)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq);
    lightVec *= lightVecD;
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    float LdN = dot(normalWorld, lightVec);
    
    float4 vLit = WorkingLit(LdN, 0.0f, 0.0f);
    d = att * pl.Diffuse_Att1.xyz * vLit.y;
 }

// Calculates diffuse and specular lighting for a point light, including light colors
void PS_PointLightDS(PointLight pl, float3 normalWorld, float3 vertPosWorld, out float3 d, float power, float3 eyeVecW, out float3 s)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float3 halfVec = normalize((lightVec + eyeVecW));
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq );
    lightVec *= lightVecD;
    float LdN = dot(lightVec, normalWorld);
    float HdN = dot(normalWorld, halfVec);
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    
    float4 vLit = WorkingLit(LdN, HdN, power);
    d = att * pl.Diffuse_Att1.xyz * vLit.y;
    s = att * pl.Specular_Att2.xyz * vLit.z * vLit.y;
}

// Calculates specular lighting for a point light, including light colors
void PS_PointLightS(PointLight pl, float3 normalWorld, float3 vertPosWorld, float power, float3 eyeVecW, out float3 s)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float3 halfVec = normalize((lightVec + eyeVecW));
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq );
    lightVec *= lightVecD;
    float LdN = dot(lightVec, normalWorld);
    float HdN = dot(normalWorld, halfVec);
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    
    float4 vLit = WorkingLit(LdN, HdN, power);
    s = att * pl.Specular_Att2.xyz * vLit.z * vLit.y;
}

// Calculates diffuse lighting for a point light, including light color
void PS_AddPointLightD(PointLight pl, float3 normalWorld, float3 vertPosWorld, inout float3 d)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq);
    lightVec *= lightVecD;
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    float LdN = dot(normalWorld, lightVec);
    
    float4 vLit = WorkingLit(LdN, 0.0f, 0.0f);
    d += att * pl.Diffuse_Att1.xyz * vLit.y;
 }

// Calculates diffuse and specular lighting for a point light, including light colors
void PS_AddPointLightDS(PointLight pl, float3 normalWorld, float3 vertPosWorld, inout float3 d, float power, float3 eyeVecW, inout float3 s)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float3 halfVec = normalize((lightVec + eyeVecW));
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq );
    lightVec *= lightVecD;
    float LdN = dot(lightVec, normalWorld);
    float HdN = dot(normalWorld, halfVec);
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    
    float4 vLit = WorkingLit(LdN, HdN, power);
    d += att * pl.Diffuse_Att1.xyz * vLit.y;
    s += att * pl.Specular_Att2.xyz * vLit.z * vLit.y;
}

// Calculates specular lighting for a point light, including light colors
void PS_AddPointLightS(PointLight pl, float3 normalWorld, float3 vertPosWorld, float power, float3 eyeVecW, inout float3 s)
{
    float3 lightVec = pl.Position_Att0.xyz - vertPosWorld;
    float3 halfVec = normalize((lightVec + eyeVecW));
    float lightVecDSq = dot(lightVec, lightVec);
    float lightVecD = rsqrt(lightVecDSq );
    lightVec *= lightVecD;
    float LdN = dot(lightVec, normalWorld);
    float HdN = dot(normalWorld, halfVec);
    lightVecD = 1/lightVecD;
    float att = pl.Position_Att0.w + pl.Diffuse_Att1.w * lightVecD + pl.Specular_Att2.w * lightVecDSq;
    att = 1 / att;
    
    float4 vLit = WorkingLit(LdN, HdN, power);
    s += att * pl.Specular_Att2.xyz * vLit.z * vLit.y;
}
