matrix mW;      // World matrix
matrix mWVP;    // World*View*Projection matrix
matrix mWrt;    // Inverse Transpose World Rotation matrix
matrix mWVt;    // Inverse Transpose World*View matrix
vector pOV;     // Object space viewer position
vector pWL;
vector pOL;
vector cLgt;
vector cnst;
vector cHlf;

texture tBas;
texture tCube;
texture tDot;
texture tNrm;
texture tGrooves;
texture tQuadAlignment;

DWord dwCubeMipFilter = 2; // None = 0, Point = 1, Linear = 2

vertexshader vTexTangentmatrixViewScreenspace = 
	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 which outputs a 3x3 orthogonal transform which takes you from world space to 
        ; tangent space.  The result is stored in output tex coords 1,2,and 3
        ; Also, stored in tex coord 4 is a view vector
        ; which can be used in a reflect operation.
        ;
        ; 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)
        ; This sample expects the constant store to be set up in the following manner:
        ;
        ; c1       - Color of material
        ; c12..c15 - World Matrix
        ; c16..c19 - Composite World-View-Projection Matrix
        ; c20..c23 - Env Transform Matrix  (object to world or view coord transform (depends on type of env mapping you want to do) )
        ; c28      - ModelSpace Camera Position
        ; c95      - 0, .5, 1, 2
        vs.1.0
        def c2, 0.5, 0.25, 1, 1

        ; OutPos = ObjSpacePos * Composite World-View-Projection Matrix
        m4x4   oPos, v0, c16
        mov    oT0.xy, v7		;passthrough texcoord 0 for bump map addressing

        ;derive per vertex eye vector using camera position   
        add		r8, c28, -v0	 ;view direction
        m3x3	r9, r8, c20      ;transform view vector from object space to env space
        dp3	    r11.x, r9, r9	   ; magnitude^2
        rsq	    r11.y, r11.x	   ; 1/mag
        mul     oT4.xyz, r9, r11.y ; normalize

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

        ; upper 3x3 of world matrix by upper tangent space transposed
        dp3		r9.x, c20, r7
        dp3		r9.y, c20, r8
        dp3		r9.z, c20, r3

        dp3		r10.x, c21, r7
        dp3		r10.y, c21, r8
        dp3		r10.z, c21, r3

        dp3		r11.x, c22, r7
        dp3		r11.y, c22, r8
        dp3		r11.z, c22, r3

        mov oT1.xyz, r9		;3x3 tangent space to world space transform
        mov oT2.xyz, r10	;
        mov oT3.xyz, r11	;

        ; Screen aligned coordinates
        m4x4   r0, v0, c16
        mul    r0, r0, c2
        mul    oT5, r0, c95.y
    };

pixelshader ps14_AnisoReflect = asm
{
    ps.1.4
    def c0, 1, 1, 1, 1
    texld   r1, t0              ; Look up normal map.
    texld   r3, t0              ; Look up groove map.
    texcrd  r0.rgb, t1          ; 1st row of environment matrix
    texcrd  r2.rgb, t2          ; 2st row of environment matrix
    texcrd  r5.rgb, t3          ; 3rd row of environment matrix
    texld   r4, t5_dw.xyw       ; Quad alignment map
;    texcrd  r2, t4              ; Eye vector

    dp3     r0.a, r3_bx2, r4_bx2
    mul     r0.rgb, r3_bx2, r4_bx2
    mad     r0.rgb, r0, r0.a, r1_bx2
    dp3     r4.r, r0, r0        ; 1st row of matrix multiply
    dp3     r4.g, r2, r0        ; 2nd row of matrix multiply
    dp3     r4.b, r5, r0        ; 3rd row of matrix multiply
;    dp3_x2  r3.rgb, r4, r1_bx2      ; 2(N.Eye)
;    mul     r3.rgb, r4, r3          ; 2N(N.Eye)
;    dp3     r2.rgb, r4, r4          ; N.N
;    mad     r2.rgb, -r1_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) 

    phase

    texld   r2, r4              ; Sample cubic reflection map

    mov r0.rgb, r2
   +mov r0.a, c0

;    texld   r3, t0              ; Sample base map
;    texld   r4, r4              ; Sample cubic diffuse map
;    texld   r5, t0              ; Sample gloss map

;    mul     r1.rgb, r5, r2       ; Specular = Gloss*Reflection
;    mad     r0.rgb, r3, r4_x2, r1   ; Base*Diffuse + Specular
;    +mov    r0.a, r3
};

String ps14_AnisoReflect_desc = "PS 1.4 - Cubic Environment Bumped Diffuse and Independently Colored Reflections";

technique ps14_AnisoReflect
{
    pass P0 
    {
        VertexShaderConstant[12] = <mW>;    // World
        VertexShaderConstant[16] = <mWVP>;  // World*View*Proj Matrix
        VertexShaderConstant[20] = <mWrt>;  // World Rotation Inv Transpose used for Eye vector transform
        VertexShaderConstant[28] = <pOV>;   // Object space Viewer position
        VertexShaderConstant[31] = <pWL>;   // World space light position
        VertexShaderConstant[32] = <pOL>;   // Object space Light position
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[95] = <cnst>;
        VertexShader = <vTexTangentmatrixViewScreenspace>;

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

        Texture[1]   = <tDot>;
        AddressU[1]  = Wrap;
        AddressV[1]  = Wrap;
        MagFilter[1] = Linear;
        MinFilter[1] = Linear;
        MipFilter[1] = Linear;

        Texture[2]   = <tCube>;
        AddressU[2]  = Clamp;
        AddressV[2]  = Clamp;
        MagFilter[2] = Anisotropic;
        MinFilter[2] = Anisotropic;
        MipFilter[2] = Point;
        MaxAnisotropy[2] = 16;

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

        Texture[4]   = <tQuadAlignment>;
        AddressU[4]  = Wrap;
        AddressV[4]  = Wrap;
        MagFilter[4] = Point;
        MinFilter[4] = Point;
        MipFilter[4] = None;

        PixelShader  = <ps14_AnisoReflect>;
    }
}

