//-----------------------------------------------------------------------------
// ps14_Ghost.sha
// 
// A cute ghostly shader based on Dan Baker of Microsoft's ideas.
// The eye vector is dotted with the normal to get an angle of incidence which
// is used to look up a texture as a function lookup which is soft around the 
// edges, opaque just inside, and then transparent in the middle.  Without the 
// soft edge, the shape of the object is too hard and not ghostly looking.
//
// This version was derived from a fresnel effect on the cubic environment 
// mapping shader which is why the tangent space to world space matrix is 
// interpolated.  So this effect could be used with cubic environment mapping,
// but otherwise could be simplified from where it is below.
//
//    Chris Brennan - ATI Research, Inc. - 2001
//-----------------------------------------------------------------------------

matrix mW;      // World matrix
matrix mWV;     // World*View 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;
vector pCenter = (0.0f,0.0f,0.0f,1.0f); // Object's center
vector cFogginess = (1.0f, 0.0f, 0.0f, 0.0f);

texture tNormal;
texture tNormalizer;
texture tGhost;

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

vertexshader vTexTangentmatrixViewLight = 
	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
        ; c29      - ModelSpace Center
        ; c30      - X = Fogginess which is 1/(distance of full fog)
        ; c32..c35 - World*View Matrix
        ; c95      - 0, .5, 1, 2
        vs.1.0

        ; 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	r10.xyz, r8, c20     ;transform view vector from object space to env space
		dp3     r11.x, r10, r10      ; length^2
		rsq     r11.y, r11.x         ; 1/length
		mul     oT4.xyz, r10, r11.y  ; normalized
        
		;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	;

        ; Calculate distance from the point away from the middle of the object.
        mov r2, c29;
        dp4 r1.z, r2, c34     ; View space Object Center
        dp4 r0.z, v0, c34     ; View space position
        sub r2.z, r0.z, r1.z  ; Distance between point and the center plane of the object.
        max r2.z, r2.z, -r2.z ; Absolute value
        mul r3.z, r2.z, c30.x ; fog amount
        mul r3.z, r3.z, r3.z  ; fog amount
        mul r3.z, r3.z, r3.z  ; fog amount
        mov oD0, r3.z
    };

pixelshader ps14_Ghost = asm
{
    ps.1.4
    def c0, 0.1f, 0.5f, 0.0f, 1.0f

    texld  r0, t0              ; Look up normal map.
    texcrd r1.rgb, t4          ; Eye vector through normalizer cube map
    texcrd r4.rgb, t1          ; 1st row of environment matrix
    texcrd r2.rgb, t2          ; 2st row of environment matrix
    texcrd r3.rgb, t3          ; 3rd row of environment matrix

    dp3     r4.r, r4, r0_bx2   ; 1st row of matrix multiply
    dp3     r4.g, r2, r0_bx2   ; 2nd row of matrix multiply
    dp3     r4.b, r3, r0_bx2   ; 3rd row of matrix multiply
    dp3     r5, r4, r1         ; (N.Eye)
    mul     r0, r5, r5

    phase

    texld r2, r0

    mov r0.rgb, r2
    +mov r0.a, r0.g
    mul r0.rgb, c0, r0
};

String ps14_Ghost_desc = "PS 1.4 - Ghost Shader";

technique ps14_Ghost
{
    pass P0 
    {
        CullMode = None;

        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[95] = <cnst>;
        VertexShader = <vTexTangentmatrixViewLight>;

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

        Texture[1]   = <tNormalizer>;
        AddressU[1]  = Clamp;
        AddressV[1]  = Clamp;
        MagFilter[1] = Linear;
        MinFilter[1] = Linear;
        MipFilter[1] = Point;

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

        PixelShader  = <ps14_Ghost>;

        ZWriteEnable = False;
        AlphaBlendEnable = True;
        SrcBlend = One;
        DestBlend = One;
    }
}
