//-----------------------------------------------------------------------------
// ps14_AnisoLight.sha
// 
// Same as the ps11_AnisoLight shader, but reads the per pixel normal and
// perturbs and re-orthogonalizes the tangent before looking up the aniso map.
//-----------------------------------------------------------------------------

matrix mWVP;    // World*View*Projection matrix
matrix mWrt;     // Inverse World
matrix mW1;     // Inverse World
vector pOV;     // Object space viewer position
vector pOL;
vector cnst;

texture tNormal;
texture tGloss;
texture tAniso;
texture tAnisoDirection;

DWord cAmbient = 0x40404040;

vertexshader vAnisoLight = 
	decl
	{
		stream 0;
		float    v0[3];  // Position
		D3DCOLOR v3;     // Normal
		float    v7[2];  // Tex coord 0
		D3DCOLOR v8;     // Binormal
		D3DCOLOR v9;     // Tangent
	}
	asm
	{
        ; Sample vertex shader for per pixel anisotropic lighting 
        ;
        ;        [Lx  Ly  Lz] [Tx]
        ;        [Vx  Vy  Vz]*[Ty]
        ;        [0   0   1]  [Tz]
        ;
        ; This sample expects the incoming vertex data to be set up as follows:
        ;
        ; v0     - Vertex Position
        ; v3	 - Vertex Normal
        ; v7	 - Vertex 2D Bumpmap Texture Coords
        ; v8	 - Vertex Tangent (normalized assumed to be positive v direction for tangent space)
        ; v9     - Vertex binormal
        ; This sample expects the constant store to be set up in the following manner:
        ;
        ; c16..c19 - Composite World-View-Projection Matrix

        ; c28      - Model Space Camera Position
        ; c32      - Model Space Light position
        ; c95      - 0, .5, 1, 2


        vs.1.0

        ; Convert from D3DColor to -1 to 1
        mad  r7, v3, c95.wwwz, -c95.zzzx ; Normal   = (v3*2.0)-1.0
        mad  r8, v8, c95.wwwz, -c95.zzzx ; TangentU = (v8*2.0)-1.0
        mad  r9, v9, c95.wwwz, -c95.zzzx ; TangentV = (v9*2.0)-1.0

        ;derive per vertex eye vector using camera position   
        ;find view vector		
        ; (if assuming an infinite viewer replace below 4 lines with mov (r1,c28) )
        add		r2, c28, -v0	;viewer direction V

        ;transform view vector into tangent space
        dp3      r3.x, r2, r9
        dp3      r3.y, r2, r8
        dp3      r3.zw, r2, r7     ;z is only needed for normalization

        ;normalize vector after reflection
        dp3		r11.x, r3, r3	   ;magnitude
        rsq		r11.y, r11.x	   ;normailize
        mul		r3, r3, r11.y	   ;tangent space view vector in r3

        ;get normalized tangent space light vector
        add      r2, c32, -v0

        ;transform light vector into tangent space
        dp3      r4.x, r2, r9
        dp3      r4.y, r2, r8
        dp3      r4.zw, r2, r7

        ;normalize vector after reflection
        dp3		r11.x, r4, r4	   ;magnitude
        rsq		r11.y, r11.x	   ;normailize
        mul		r4, r4, r11.y	   ;tangent space reflection vector in r3

        ; OutPos = ObjSpacePos * Composite World-View-Projection Matrix
        m4x4   oPos, v0, c16

        mov oT0.xy, v7       		;passthrough texcoord 0 for bump map addressing

        mov oT1.xyz, r4
        mov oT2.xyz, r3

    };

pixelshader ps14_AnisoLight = asm
{
    ;
    ; t2 contains tangent-space L vector          ; 0.5Lx, 0.5Ly, 0.5, 0
    ; t3 contains tangent-space reflection vector ; 0.5Vx, 0.5Vy, 0.5, 0

    ;
    ; Map bound at stage 0 is a normal map
    ; Map bound at stage 3 is a T.L x T.V map as the z positive face of a cube map
    ;
    ps.1.4
    def c0, 0.5f, 0.5f, 0.0f, 1.0f

    texld  r0, t0                 ; Contains direction of anisotropy in tangent space
    texcrd r2.rgb, t1             ; light vector
    texcrd r3.rgb, t2             ; view vector
    texld  r4, t0                 ; normal map

    ; Perturb anisotropy lighting direction by normal
    mov r0.z, c0.x                 ; Zero out z on tangent needed if we use the same art as ps11
    dp3 r1.xyz, r0_bx2, r4_bx2     ; Aniso.Normal
    mad r0.xyz, r4_bx2, r1, r0_bx2 ; Aniso - N(Aniso.Normal)

    ; Calculate A.View and A.Light for looking up into function map.
    dp3 r1.x, r2, r0       ; Perform second row of matrix multiply.
    dp3 r1.yz, r3, r0      ; Perform second row of matrix multiply to get a
                           ; 3-vector with which to sample texture 3, which is
				           ; a look-up table for aniso lighting
    mad r1.rg, r1, c0, c0  ; Scale and bias for lookup

    ; Diffuse Light Term
    dp3_sat r4.rgb, r4_bx2, r2 ; N.L

    phase

    texld  r2, r1                 ; Anisotropic lighting function lookup
    texld  r3, t0                 ; gloss map

    mul r4.rgb, r3, r4.b       ;basemap * N.L
    mad r0.rgb, r3, r2.a, r4   ;+= glossmap * specular
    mad r0.rgb, r3, c7, r0     ;+= ambient * basemap
   +mov r0.a, r0.b
};

String ps14_AnisoLight_desc = "PS 1.4 - Per Pixel Bumped Anisotropic Lighting plus Diffuse";

technique ps14_AnisoLight
{
    pass P0 
    {
        VertexShader = <vAnisoLight>;
        VertexShaderConstant[16] = <mWVP>;  // World*View*Proj Matrix
        VertexShaderConstant[20] = <mW1>;   // World Inverse
        VertexShaderConstant[28] = <pOV>;   // Object space Viewer position
        VertexShaderConstant[32] = <pOL>;   // Object space Light position
        VertexShaderConstant[95] = <cnst>;

        Texture[0]   = <tAnisoDirection>;
	    AddressU[0]  = Wrap;
	    AddressV[0]  = Wrap;
        MagFilter[0] = Linear;
        MinFilter[0] = Linear;
        MipFilter[0] = Linear;

        Texture[2]   = <tAniso>;
	    AddressU[2]  = Clamp;
	    AddressV[2]  = Clamp;
        MagFilter[2] = Linear;
        MinFilter[2] = Linear;
        MipFilter[2] = Linear;

        Texture[3]   = <tGloss>;
	    AddressU[3]  = Wrap;
	    AddressV[3]  = Wrap;
        MagFilter[3] = Linear;
        MinFilter[3] = Linear;
        MipFilter[3] = Linear;

        Texture[4]   = <tNormal>;
	    AddressU[4]  = Wrap;
	    AddressV[4]  = Wrap;
        MagFilter[4] = Linear;
        MinFilter[4] = Linear;
        MipFilter[4] = Linear;

        PixelShaderConstant[7] = <cAmbient>;
        PixelShader  = <ps14_AnisoLight>;
    }
}
