//-----------------------------------------------------------------------------
// BumpSpot.sha
// 
// 2 bumped spot lights.  The bump map, falloff and angle attentuation are 
// all per pixel calculations.
//
// The distance and angle are calculated per light and used to look up a 2d
// texture which returns the intensity of the light.
//
// A scale and add is used on the angle after the dot product with the light
// direction to widen the spot and change the size and slope of the 
// umbra and penumbra.
//
//    Chris Brennan - ATI Research, Inc. - 2001
//-----------------------------------------------------------------------------

matrix  mWVP;
matrix  mW;
vector  pWL5;
vector  pOL5;
vector  cLgt5;
vector  cOLgtDir5;
vector  pWL6;
vector  pOL6;
vector  cLgt6;
vector  cOLgtDir6;
vector  cnst;

texture tBase;          // Base texture
texture tNormal;        // Normal Map
texture tNormalizer;    // Cubic Normalizer map
texture tSpotIntensity; // Falloff and angle map

DWord cLight  = 0x00000000;
DWord cLight2 = 0x00000000;
DWord cLight3 = 0x00000000;
DWord cLight4 = 0x00000000;
DWord cLight5 = 0xffff0080;
DWord cLight6 = 0xff80ffff;

DWord dwNumLights = 6;

DWord cAmbient = 0x40404040;

vertexshader vSpot = 
	decl
	{
		stream 0;
		float    v0[3];  // Position
		D3DCOLOR v3;     // Normal
		float    v7[2];  // Tex coord 0
		D3DCOLOR v8;     // Binormal
		D3DCOLOR v9;     // Tangent
	}
	asm
	{
        ; Constants:
        ; 16..19 - Composite World-View-Projection Matrix
        ; 24..27 - World Matrix
        ;
        ; Light 1:
        ; 31     - World Space Light Position
        ; 32     - Object Space Light Position
        ; 33     - {1/light range, light range, 1/attenuation2, attenuation2}
        ; 34     - Object Space Light Direction
        ;
        ; Light 2:
        ; 41     - World Space Light Position
        ; 42     - Object Space Light Position
        ; 43     - {1/light range, light range, 1/attenuation2, attenuation2}
        ; 44     - Object Space Light Direction
        ;
        ; 95     - {0.0, 0.5, 1.0, 2.0}

		vs.1.0
		
		m4x4 oPos, v0, c16
	    mov  oT0.xy, v7.xy   ; Base Texture

		;r9 = tangent U vector = normal cross tangent V vector
        mad  r3, v3, c95.wwwz, -c95.zzzx ; Normal = (v3*2.0)-1.0
        mad  r9, v8, c95.wwwz, -c95.zzzx ; TangentU = (v8*2.0)-1.0
        mad  r8, v9, c95.wwwz, -c95.zzzx ; TangentV = (v9*2.0)-1.0

        ;Object->World space scale
        dp3  r11.x, c24, c24
        rsq  r11.x, r11.x
        rcp  r11.x, r11.x

        ;Light 1
		;r5 = tangent space light vector 
		sub  r1, c32, v0     ; Object space light to point vector
        mul  r1, r1, r11.x
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
        mul  oT1.xyz, r5, c33.x ; Tangent Space Light Position (vLP scaled by the light's range)
        mul  r1, c34, r11.x
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT2.xyz, r5.xyz ; Tangent Space Light direction

        ;Light 2
		;r5 = tangent space light vector 
		sub  r1, c42, v0     ; Object space light to point vector
        mul  r1, r1, r11.x
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
        mul  oT3.xyz, r5, c43.x ; Tangent Space Light Position (vLP scaled by the light's range)
        mul  r1, c44, r11.x
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT4.xyz, r5.xyz ; Tangent Space Light direction
    };

pixelshader ps14_2_Spot = asm
{
    ps.1.4

    def c0, 1.0f, 1.0f, 1.0f, 1.0f ; Light 1 Color
    def c1, 1.0f, -0.72f, 1.0f, 1.0f ; Light 1 Angle scale(x) and bias(Y)
    def c2, 1.0f, 1.0f, 1.0f, 1.0f ; Light 2 Color
    def c3, 0.25f, 0.03f, 1.0f, 1.0f ; Light 2 Angle scale(x) and bias(Y)

    texcrd r0.rgb, t2  ; Spot light 1 direction
    texcrd r1.rgb, t4  ; Spot light 2 direction
    texld  r2, t1      ; Light 1 to Point vector
    texld  r3, t3      ; Light 2 to Point vector
    texcrd r4.rgb, t1  ; Light 1 space position for attenuation
    texcrd r5.rgb, t3  ; Light 2 space position for attenuation

    dp3_sat r4.x, r4, r4          ; Light 1 Distance^2
    dp3_sat r5.x, r5, r5          ; Light 2 Distance^2
    dp3_sat r4.y, r0, r2_bx2      ; Light 1 Angle from center of spotlight
    dp3_sat r5.y, r1, r3_bx2      ; Light 2 Angle from center of spotlight

    mad_x4  r4.y, r4.y, c1.x, c1.y  ; Light 1 scale and bias for angle
    mad_x4  r5.y, r5.y, c3.x, c3.y  ; Light 2 scale and bias for angle

    phase

    texld  r0, t0      ; Base Map
    texld  r1, t0      ; Normal Map
;   texcrd r2.rgb, r2  ; Light to point vector
;   texcrd r3.rgb, r3  ; Light to point vector
    texld  r4, r4      ; Distance/Angle lookup map
    texld  r5, r5      ; Distance/Angle lookup map

    dp3_sat r2.rgb, r1_bx2, r2_bx2 ; *= (N.L1)
    mul_x2  r2.rgb, r2, r4.r       ; Attenuation from distance and angle
    mad     r2.rgb, r2, c0, c7     ; * Light Color + Ambient

    dp3_sat r3.rgb, r1_bx2, r3_bx2 ; *= (N.L2)
    mul_x2  r3.rgb, r3, r5.r       ; Attenuation from distance and angle
    mad     r3.rgb, r3, c2, r2     ; * Light 2 Color + Light 1 Color + Ambient

    mul     r0.rgb, r3, r0     ; Modulate by base map
   +mov     r0.a, c0

};

String ps14_2_Spot_desc = "PS 1.4 - 2 Spot Lights";

technique ps14_2_Spot  // Dot3 diffuse bump mapping
{
    pass P0
    {
        VertexShaderConstant[0]  = <dwNumLights>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[24] = <mW>;
        VertexShaderConstant[31] = <pWL5>;
        VertexShaderConstant[32] = <pOL5>;
        VertexShaderConstant[33] = <cLgt5>;
        VertexShaderConstant[34] = <cOLgtDir5>;
        VertexShaderConstant[41] = <pWL6>;
        VertexShaderConstant[42] = <pOL6>;
        VertexShaderConstant[43] = <cLgt6>;
        VertexShaderConstant[44] = <cOLgtDir6>;
        VertexShaderConstant[95] = <cnst>;

        vertexshader = <vSpot>;	

        // Base Map
	    Texture[0]       = <tBase>;
	    AddressU[0]      = Wrap;
	    AddressV[0]      = Wrap;
	    MinFilter[0]     = Linear;
	    MagFilter[0]     = Linear;
	    MipFilter[0]     = Linear;

        // Normal Map
        Texture[1]       = <tNormal>;
        AddressU[1]      = Wrap;
        AddressV[1]      = Wrap;
        MinFilter[1]     = Linear;
        MagFilter[1]     = Linear;
        MipFilter[1]     = Linear;

        // Cubic Normalizer Map
	    Texture[2]   = <tNormalizer>;
	    AddressU[2]  = Clamp;
	    AddressV[2]  = Clamp;
	    MinFilter[2] = Linear;
	    MagFilter[2] = Linear;
	    MipFilter[2] = Point;

        // Cubic Normalizer Map
	    Texture[3]   = <tNormalizer>;
	    AddressU[3]  = Clamp;
	    AddressV[3]  = Clamp;
	    MinFilter[3] = Linear;
	    MagFilter[3] = Linear;
	    MipFilter[3] = Point;

        // Attenuation and spot light angle map
	    Texture[4]   = <tSpotIntensity>;
	    AddressU[4]  = Clamp;
	    AddressV[4]  = Clamp;
	    MinFilter[4] = Linear;
	    MagFilter[4] = Linear;
	    MipFilter[4] = Point;

        // Attenuation and spot light angle map
	    Texture[5]   = <tSpotIntensity>;
	    AddressU[5]  = Clamp;
	    AddressV[5]  = Clamp;
	    MinFilter[5] = Linear;
	    MagFilter[5] = Linear;
	    MipFilter[5] = Point;

        PixelShader = <ps14_2_Spot>;
        PixelShaderConstant[0] = <cLight5>;
        PixelShaderConstant[2] = <cLight6>;
        PixelShaderConstant[7] = <cAmbient>;
    }
}

