//-----------------------------------------------------------------------------
// ChestMetal.sha
// 
// Basic environment map shader used on chest and bars with fallbacks.
//-----------------------------------------------------------------------------

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;     // World space light position
vector pOL;     // Object space light position
vector cLgt;    // Light range and attenuation
vector cnst;    // Object space viewer position

texture tCube;
texture tNormal;

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

//--------------------------------------------------------------
// Pixel Shader 1.0 - 1.1 Section
//--------------------------------------------------------------
// Cubic bump mapping
vertexshader vTangent123 = 
	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 the w component of these vectors is a per vertex normalized view vector
        ; which can be used for the texm3x3vspec  pixel shader 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)
        ; v9   - vertex binormal
        ; This sample expects the constant store to be set up in the following manner:
        ;
        ; 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
        ; c31      - WorldSpace Light Position
        ; c32      - ModelSpace Light Position
        ; c95      - 0, .5, 1, 2

        vs.1.0

        ;derive per vertex eye vector using camera position   
        add		r8, c28, -v0	;view direction
        dp3		r11.x, r8, r8	;magnitude
        rsq		r11.y, r11.x	;normalize
        mul		r8, r8, r11.y	;normalized direction vector 

        m3x3	   r2, r8, c20	;transform reflection vector from object space to env space

		;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


        ;pack normalized view vector in 
        mov     r9.w, r2.x
        mov     r10.w, r2.y
        mov     r11.w, r2.z


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

        mov oT0, v7		;passthrough texcoord 0 for bump map addressing
        mov oT1, r9		;3x3 tangent space to world space transform
        mov oT2, r10	;
        mov oT3, r11	;

        ; Light
        sub  r0, v0, c32     ; Object space light direction
		dp3  r11.x, r0, r0   ; length^2
		rsq  r11.y, r11.x    ; 1/length
		mul  r0, r0, r11.y   ; normalized
        dp3  r4, r3, -r0     ; N.L

        ; attenuation = (1/attenuation2)/D^2
		m4x4 r0, v0, c12             ; World Space Position
		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  r2.z, r2.y, r4.x        ; *= N.L
        mul  r0, c1, r2.z            ; *= color
        mul  oD0, r0, c1.w           ; *= color

    };

pixelshader ps11_BumpVSpec = asm
{
    ps.1.1

    tex t0                  ; Define t0 as a standard 3-vector.
    texm3x3pad t1, t0_bx2   ; Perform first row of matrix multiply.
    texm3x3pad t2, t0_bx2   ; Perform second row of matrix multiply.
    texm3x3vspec t3, t0_bx2 ; Perform third row of matrix multiply, 
					        ; do reflection calculation
                            ; using eye ray, and sample texture 3
                            ; specular map.
    mad r0, c0, t3, v0
};

String ps11_CubicBumpMapping_desc = "PS 1.0 - Cubic Environment Bump Mapping";

technique ps11_CubicBumpMapping
{
    pass P0 
    {
        VertexShaderConstant[1]  = <cColor>;
        VertexShaderConstant[12] = <mW>;    // World
        VertexShaderConstant[16] = <mWVP>;  // World*View*Proj Matrix
        VertexShaderConstant[20] = <mWrt>;  // World Rotation Inv Transpose
        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 = <vTangent123>;

        Texture[0]   = <tNormal>;
        MagFilter[0] = Linear;
        MinFilter[0] = Linear;
        MipFilter[0] = Linear;

        Texture[3]   = <tCube>;
	    AddressU[3]  = Clamp;
	    AddressV[3]  = Clamp;
        MagFilter[3] = Linear;
        MinFilter[3] = Linear;
        MipFilter[3] = <dwCubeMipFilter>;

        PixelShaderConstant[0] = <cColor>;
        PixelShader  = <ps11_BumpVSpec>;
    }
}

pixelshader ps10_GoldReflect = asm
{
    ps.1.0
    tex t0
    mad r0, c0, t0, v0
};


vertexshader vBasCubemap = 
	decl
	{
		stream 0;
		float    v0[3];  // Position
		D3DCOLOR v3;     // Normal
		float    v7[2];  // Tex coord 0
		D3DCOLOR v8;     // Binormal
		D3DCOLOR v9;     // Tangent
	}
	asm
	{
        vs.1.0
        ; Constants
        ;
        ; 1      - Object Color 
        ;
        ; c12..c15 - World Matrix
        ; 16..19   - Composite World-View-Projection Matrix
        ; 20..23   - Inverse Transpose World-View Matrix
        ; 24       - ObjectSpace Camera Position
        ; 33       - {1/light range, light range, 1/attenuation2, attenuation2}
        ;
        ; 95       - {0.0, 0.5, 1.0, 2.0}
        def c93, 0.0f, 2.5f, 0.0f, 0.0f     ; Center of the cube map
        def c94, 0.1f, 0.33f, 0.20f, 0.18f  ; Scalar for cube map adjustment 
                                            ; = roughly 1/Radius of environment map.

        mad     r3, v3, c95.wwwz, -c95.zzzx ; Normal direction in object space

        ; Light
        sub  r0, v0, c32     ; Object space light direction
		dp3  r11.x, r0, r0   ; length^2
		rsq  r11.y, r11.x    ; 1/length
		mul  r0, r0, r11.y   ; normalized
        dp3  r4, r3, -r0 

        ; attenuation = (1/attenuation2)/D^2
		m4x4 r0, v0, c12             ; World Space Position
		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  r2.z, r2.y, r4.x        ; *= N.L
        mul  r0, c1, r2.z            ; *= color
        mul  oD0, r0, c1.w           ; *= color

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

        mov		r0, v0			            ; vertex position in object space 

        ;find view vector
        sub		r1, r0, c24 	;viewer direction

        ;find reflected view vector W=V-(2V.N)N
        add     r2, r1, r1		;2V
        dp3		r11.x, r2, r3	;2V.N
        mad		r2, r3, -r11.x, r1 ; W=V-(2V.N)N

        ; Viewspace Reflect = ObjSpaceReflect * Inverse Transpose World-View Matrix
        ;  Assuming upper 3x3 is orthonormal if not, then normalize r3 after this
        m3x3    r3, r2, c20
        dp3		r11.x, r3, r3	;length^2
        rsq		r11.y, r11.x	;1/length
        rcp		r11.z, r11.y	;length

        ; Calculate a adjustment amount to account for cube map center not being at this object's centroid.
        m3x3 r0, v0, c12
        sub r0, r0, c93         ; vCemP = CenterOfEnvMap - ObjectPosition   -- Vector from cube center to point.
        mul r0, r0, r11.z       ; vCemP*|vReflect|
        mad oT0, r0, c94.z, r3  ; vReflect' = vReflect+vCemP*|vReflect|*EnvMapRadius
  };

String ps10_ColoredCubeReflection_desc = "PS 1.0 - Tinted Cubic Environment Bump Mapping";

technique ps10_ColoredCubeReflection
{
    pass P0 
    {
        VertexShaderConstant[1]  = <cColor>;
        VertexShaderConstant[12] = <mW>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[20] = <mWrt>;
        VertexShaderConstant[24] = <pOV>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[95] = <cnst>;
        VertexShader = <vBasCubemap>;

        // Stage0
        Texture[0] = <tCube>;
        AddressU[0]  = Clamp;
        AddressV[0]  = Clamp;
        MinFilter[0] = Linear;
        MagFilter[0] = Linear;
        MipFilter[0] = <dwCubeMipFilter>;

        PixelShaderConstant[0] = <cColor>;
        PixelShader = <ps10_GoldReflect>;
     }
}

//--------------------------------------------------------------
// Fixed function pixel pipe fallback
//--------------------------------------------------------------
String Fixed_CubeMap_desc = "Fixed Function - Tinted Cubic Environment Bump Mapping";

technique Fixed_CubeMap
{
    pass P0 
    {
        VertexShaderConstant[1]  = <cColor>;
        VertexShaderConstant[12] = <mW>;
        VertexShaderConstant[16] = <mWVP>;
        VertexShaderConstant[20] = <mWrt>;
        VertexShaderConstant[24] = <pOV>;
        VertexShaderConstant[31] = <pWL>;
        VertexShaderConstant[32] = <pOL>;
        VertexShaderConstant[33] = <cLgt>;
        VertexShaderConstant[95] = <cnst>;
        vertexshader = <vBasCubemap>;

        TextureFactor = <cColor>;

        // Stage0
        Texture[0] = <tCube>;
        TexCoordIndex[0] = 0;
        AddressU[0]  = Clamp;
        AddressV[0]  = Clamp;
        MinFilter[0] = Linear;
        MagFilter[0] = Linear;
        MipFilter[0] = <dwCubeMipFilter>;

        ColorOp[0]   = Modulate; //MultiplyAdd
        ColorArg1[0] = Texture;
        ColorArg2[0] = TFactor;
        ColorArg0[0] = Diffuse;
        AlphaOp[0]   = Modulate;
        AlphaArg1[0] = Texture;
        AlphaArg2[0] = TFactor;
        AlphaArg0[0] = Diffuse;
     }
}

