//-----------------------------------------------------------------------------
// ps14_MultiLightBump.sha
// 
// A test to see how many bumped lights can be crammed into one pass of rendering.
//
//    Chris Brennan - ATI Research, Inc. - 2001
//-----------------------------------------------------------------------------

matrix  mWVP;
matrix  mW;
vector  pWL;
vector  pOL;
vector  cLgt;
vector  pWL2;
vector  pOL2;
vector  cLgt2;
vector  pWL3;
vector  pOL3;
vector  cLgt3;
vector  pWL4;
vector  pOL4;
vector  cLgt4;
vector  cnst;

texture tBase;       // Base texture
texture tNormal;     // Normal Map
texture tNormalizer; // Cubic Normalizer map

DWord cLight  = 0xffff8000;
DWord cLight2 = 0xff0080ff;
DWord cLight3 = 0xff80ff00;
DWord cLight4 = 0xff8000ff;
DWord cLight5 = 0xff00ff80;

DWord dwNumLights = 4;

DWord cAmbient = 0x40404040;

vertexshader vTexLight4 = 
	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..36 - Light 2 consts
        ; 37..39 - Light 3 consts
        ; 40..42 - Light 4 consts
        ;
        ; 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

		m4x4 r0, v0, c24             ; World Space Position

        ;Light 1
		;r5 = tangent space light vector 
		sub  r1, c32, v0     ; Object space light direction
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT1.xyz, r5.xyz ; Tangent Space Light vector

        ; attenuation = (1/attenuation2)/D^2
		sub  r1, r0, c31             ; World Space Light direction
		dp3  r11.x, r1, r1           ; Distance^2
		rcp  r2.x, r11.x             ; recip = 1/D^2
        mul  r2.y, r2.x, c33.z       ; *= 1/attenuation2
		mul  oD0.x, r2.y, c95.y      ; *= .5

        ;Light 2
		;r5 = tangent space light vector 
		sub  r1, c35, v0     ; Object space light direction
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT2.xyz, r5.xyz ; Tangent Space Light vector

        ; attenuation = (1/attenuation2)/D^2
		sub  r1, r0, c34             ; World Space Light direction
		dp3  r11.x, r1, r1           ; Distance^2
		rcp  r2.x, r11.x             ; recip = 1/D^2
        mul  r2.y, r2.x, c36.z       ; *= 1/attenuation2
		mul  oD0.y, r2.y, c95.y      ; *= .5

        ;Light 3
		;r5 = tangent space light vector 
		sub  r1, c38, v0     ; Object space light direction
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT3.xyz, r5.xyz ; Tangent Space Light vector

        ; attenuation = (1/attenuation2)/D^2
		sub  r1, r0, c37             ; World Space Light direction
		dp3  r11.x, r1, r1           ; Distance^2
		rcp  r2.x, r11.x             ; recip = 1/D^2
        mul  r2.y, r2.x, c39.z       ; *= 1/attenuation2
		mul  oD0.z, r2.y, c95.y      ; *= .5

        ;Light 4
		;r5 = tangent space light vector 
		sub  r1, c41, v0     ; Object space light direction
		dp3  r5.x, r9, r1
		dp3  r5.y, r8, r1
		dp3  r5.z, r3, r1
		mov  oT4.xyz, r5.xyz ; Tangent Space Light vector

        ; attenuation = (1/attenuation2)/D^2
		sub  r1, r0, c40             ; World Space Light direction
		dp3  r11.x, r1, r1           ; Distance^2
		rcp  r2.x, r11.x             ; recip = 1/D^2
        mul  r2.y, r2.x, c42.z       ; *= 1/attenuation2
		mul  oD0.w, r2.y, c95.y      ; *= .5

    };

pixelshader ps14_1_Light_Dot3_Diff = asm
{
    ps.1.4
    texld r0, t0
    texld r1, t0
    texld r2, t1

    ; Light 1
    dp3_sat r2.rgb, r1_bx2, r2_bx2 ; *= (N.L)
    mul_x2  r2.rgb, r2, c0         ; *= Light Color
    
    mul     r1.rgb, r2, v0.x     ; Attenuate light 1

    add     r1.rgb, r1, c7
    mul     r0.rgb, r1, r0     ; Modulate by base map
};

String ps14_1_Light_Dot3_Diffuse_desc = "PS 1.4 - Diffuse Bump Mapping";

technique ps14_1_Light_Dot3_Diffuse  // Dot3 diffuse bump mapping
{
    pass P0
    {
        VertexShaderConstant[0]  = <dwNumLights>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[24] = <mW>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[95] = <cnst>;

        vertexshader = <vTexLight4>;	

        // 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;

        PixelShader = <ps14_1_Light_Dot3_Diff>;
        PixelShaderConstant[0] = <cLight>;
        PixelShaderConstant[7] = <cAmbient>;
    }
}

pixelshader ps14_2_Light_Dot3_Diff = asm
{
    ps.1.4
    texld r0, t0
    texld r1, t0
    texld r2, t1
    texld r3, t2

    ; Light 1
    dp3_sat r2.rgb, r1_bx2, r2_bx2 ; *= (N.L)
    mul_x2  r2.rgb, r2, c0         ; *= Light Color
    
    ; Light 2
    dp3_sat r3.rgb, r1_bx2, r3_bx2 ; *= (N.L)
    mul_x2  r3.rgb, r3, c1         ; *= Light Color
    
    mul  r1.rgb, r2, v0.x     ; Attenuate light 1
    mad  r1.rgb, r3, v0.y, r1 ; Attenuate light 2

    add    r1.rgb, r1, c7
    mul    r0.rgb, r1, r0     ; Modulate by base map
};

String ps14_2_Light_Dot3_Diffuse_desc = "PS 1.4 - 2 Lights/Pass Diffuse Bump Mapping";

technique ps14_2_Light_Dot3_Diffuse  // Dot3 diffuse bump mapping
{
    pass P0
    {
        VertexShaderConstant[0]  = <dwNumLights>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[24] = <mW>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt2>;
        VertexShaderConstant[34] = <pWL2>;
        VertexShaderConstant[35] = <pOL2>;
        VertexShaderConstant[36] = <cLgt2>;
        VertexShaderConstant[95] = <cnst>;

        vertexshader = <vTexLight4>;	

        // 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;

        PixelShader = <ps14_2_Light_Dot3_Diff>;
        PixelShaderConstant[0] = <cLight>;
        PixelShaderConstant[1] = <cLight2>;
        PixelShaderConstant[7] = <cAmbient>;
    }
}

pixelshader ps14_3_Light_Dot3_Diff = asm
{
    ps.1.4
    texld r1, t0
    texld r2, t1
    texld r3, t2
    texld r4, t3

    ; Light 1
    dp3_sat r2.rgb, r1_bx2, r2_bx2 ; *= (N.L)
    mul_x2  r2.rgb, r2, c0         ; *= Light Color

    ; Light 2
    dp3_sat r3.rgb, r1_bx2, r3_bx2
    mul_x2  r3.rgb, r3, c1

    ; Light 3
    dp3_sat r4.rgb, r1_bx2, r4_bx2
    mul_x2  r4.rgb, r4, c2

    phase

    texld r0, t0
    texld r5, t4
   
    mul  r1.rgb, r2, v0.x     ; Attenuate light 1
    mad  r1.rgb, r3, v0.y, r1 ; Attenuate light 2
    mad  r1.rgb, r4, v0.z, r1 ; Attenuate light 3

    add  r1.rgb, r1, c7
    mul  r0.rgb, r1, r0     ; Modulate by base map
};

String ps14_3_Light_Dot3_Diffuse_desc = "PS 1.4 - 3 Lights/Pass Diffuse Bump Mapping";

technique ps14_3_Light_Dot3_Diffuse  // Dot3 diffuse bump mapping
{
    pass P0
    {
        VertexShaderConstant[0]  = <dwNumLights>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[24] = <mW>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[34] = <pWL2>;
        VertexShaderConstant[35] = <pOL2>;
        VertexShaderConstant[36] = <cLgt2>;
        VertexShaderConstant[37] = <pWL3>;
        VertexShaderConstant[38] = <pOL3>;
        VertexShaderConstant[39] = <cLgt3>;
        VertexShaderConstant[95] = <cnst>;

        vertexshader = <vTexLight4>;	

        // 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;

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

        PixelShader = <ps14_3_Light_Dot3_Diff>;
        PixelShaderConstant[0] = <cLight>;
        PixelShaderConstant[1] = <cLight2>;
        PixelShaderConstant[2] = <cLight3>;
        PixelShaderConstant[7] = <cAmbient>;
    }
}

pixelshader ps14_4_Light_Dot3_Diff = asm
{
    ps.1.4
    texld r1, t0
    texld r2, t1
    texld r3, t2
    texld r4, t3

    ; Light 1
    dp3_sat r2.rgb, r1_bx2, r2_bx2 ; *= (N.L)
    mul_x2  r2.rgb, r2, c0         ; *= Light Color

    ; Light 2
    dp3_sat r3.rgb, r1_bx2, r3_bx2
    mul_x2  r3.rgb, r3, c1

    ; Light 3
    dp3_sat r4.rgb, r1_bx2, r4_bx2
    mul_x2  r4.rgb, r4, c2

    phase

    texld r0, t0
    texld r5, t4

    ; Light 4
    dp3_sat r5.rgb, r1_bx2, r5_bx2
    mul_x2  r5.rgb, r5, c3
    
    mul  r1.rgb, r2, v0.x     ; Attenuate light 1
    mad  r1.rgb, r3, v0.y, r1 ; Attenuate light 2
    mad  r1.rgb, r4, v0.z, r1 ; Attenuate light 3
    mad  r1.rgb, r5, v0.w, r1 ; Attenuate light 4

    add  r1.rgb, r1, c7     ; += Ambient
    mul  r0.rgb, r1, r0     ; Modulate by base map
};

String ps14_4_Light_Dot3_Diffuse_desc = "PS 1.4 - 4 Lights/Pass Diffuse Bump Mapping";

technique ps14_4_Light_Dot3_Diffuse  // Dot3 diffuse bump mapping
{
    pass P0
    {
        VertexShaderConstant[0]  = <dwNumLights>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[24] = <mW>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[34] = <pWL2>;
        VertexShaderConstant[35] = <pOL2>;
        VertexShaderConstant[36] = <cLgt2>;
        VertexShaderConstant[37] = <pWL3>;
        VertexShaderConstant[38] = <pOL3>;
        VertexShaderConstant[39] = <cLgt3>;
        VertexShaderConstant[40] = <pWL4>;
        VertexShaderConstant[41] = <pOL4>;
        VertexShaderConstant[42] = <cLgt4>;
        VertexShaderConstant[95] = <cnst>;

        vertexshader = <vTexLight4>;	

        // 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]     = Point;

        // 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;

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

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

        PixelShader = <ps14_4_Light_Dot3_Diff>;
        PixelShaderConstant[0] = <cLight>;
        PixelShaderConstant[1] = <cLight2>;
        PixelShaderConstant[2] = <cLight3>;
        PixelShaderConstant[3] = <cLight4>;
        PixelShaderConstant[7] = <cAmbient>;
    }
}
