//
// Project:
//
//   D3D RightMark
//
// Description:
//
//   Effect file for "Pixel Shading" test.
//
// Effect Version: 
//
//   DirectX 9.0 (Summer 2003 SDK Update)
//
// Shader Profile:
//
//   Pixel Shaders (various versions) ( HLSL )
//
//   Vertex Shaders (various versions) ( HLSL )
//

//
// Defines
//

// #define NORMALIZATION_CUBEMAP_A8R8G8B8 0
// #define NORMALIZATION_CUBEMAP_Q8W8V8U8 0
// #define SINUS_LUT 0
// #define POW_LUT 0
// #define HALF_PRECISION 0
// #define PS_VERSION ps_2_0
// #define VS_VERSION vs_2_0

#if HALF_PRECISION
   #define rm_float    half        
   #define rm_float2   vector<half, 2> 
   #define rm_float3   vector<half, 3> 
   #define rm_float4   vector<half, 4> 
   #define rm_float4x4 matrix<half, 4, 4> 
#else 
   #define rm_float    float 
   #define rm_float2   vector<float, 2> 
   #define rm_float3   vector<float, 3> 
   #define rm_float4   vector<float, 4> 
   #define rm_float4x4 matrix<float, 4, 4> 
#endif 

//
// Global Variables
//

#define rm_PI 3.141592654

rm_float4 vZero  = { 0.0,  0.0, 0.0, 0.0 };
rm_float4 vOne   = { 1.0,  1.0, 1.0, 1.0 };
rm_float4 vHalf  = { 0.5,  0.5, 0.5, 0.5 };
rm_float4 vBias  = { 2.0, -1.0, 0.5, 0.5 };

rm_float fGeometryScale = 0.01;

// Lights

struct rm_light
{
	rm_float4 vPosition;

	rm_float4 vDiffuse;
	rm_float4 vSpecular;

	rm_float  fAttenuation;
};

rm_light Lights[3];

// Material

rm_float fMaterialPower = 16.0;

// Misc

rm_float4   vCameraPos;	         // Camera Position

rm_float4x4 mW;		         // World Matrix
rm_float4x4 mWVP;		 // World * View * Projection Matrix

// Textures

texture texDiffuse;	         // Diffuse Map Texture      ( A8R8G8B8 format )
texture texSpecular;	         // Specular Map Texture     ( A8R8G8B8 format )

texture texNormal;	         // Normal Map Texture       ( Q8W8V8U8 format )
texture texNormalizationCubeMap; // Normalization CubeMap    ( A8R8G8B8 or Q8W8V8U8 format )

texture texNoise; 	         // Noise 3D Texture         ( A8R8G8B8 format )
texture texMarble;	         // Marble LUT Texture       ( A8R8G8B8 format )
texture texFire;	         // Fire LUT Texture         ( A8R8G8B8 format )

texture texSin;	                 // Sinus LUT Texture           ( Q8W8V8U8 format )
texture texPow;	                 // Specular Power LUT Texture  ( A8R8G8B8 format )
texture texLinear;               // Linear LUT Texture          ( A8R8G8B8 format )

// Procedural Texture Variables

rm_float fFactor;
rm_float fScale;
rm_float fInitFreq;  
rm_float fFreqScale;

rm_float4 vAmp;
rm_float4 vTime;

// Misc

int nPixelShader;
int nVertexShader;

//
// Samplers
//

sampler DiffuseMapSampler = sampler_state
{
   Texture = (texDiffuse);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};

sampler NormalMapSampler = sampler_state
{
   Texture = (texNormal);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};

sampler SpecularMapSampler = sampler_state
{
   Texture = (texSpecular);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};

sampler NoiseSampler = sampler_state
{
   Texture = (texNoise);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};

sampler MarbleSampler = sampler_state
{
   Texture = (texMarble);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = None;

   AddressU  = Clamp;
   AddressV  = Clamp;

   MaxAnisotropy = 16;
};

sampler FireSampler = sampler_state
{
   Texture = (texFire);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = None;

   AddressU  = Clamp;
   AddressV  = Clamp;

   MaxAnisotropy = 16;
};

sampler NormalizationCubeMapSampler = sampler_state
{
   Texture = (texNormalizationCubeMap);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;

   AddressU  = Clamp;
   AddressV  = Clamp;

   MaxAnisotropy = 16;
};

sampler SinSampler = sampler_state
{
   Texture = (texSin);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = None;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};


sampler PowSampler = sampler_state
{
   Texture = (texPow);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = None;

   AddressU  = Clamp;
   AddressV  = Clamp;

   MaxAnisotropy = 16;
};


sampler LinearSampler = sampler_state
{
   Texture = (texLinear);

   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = None;

   AddressU  = Wrap;
   AddressV  = Wrap;

   MaxAnisotropy = 16;
};

//
// Shaders
//

// function used to fill the noise LUT texture ( based on Microsoft's DirectX 9.0 SDK EffectEdit demo (wood shader) )

float4 GenerateNoiceFunction(float3 Pos : POSITION) : COLOR
{
 // float4 vColor;

    float4 Noise = (float4)0;

    for (int i = 1; i < 256; i += i)
    {
        Noise.r += abs(noise(Pos * 500 * i)) / i;
        Noise.g += abs(noise((Pos + 1)* 500 * i)) / i;
        Noise.b += abs(noise((Pos + 2) * 500 * i)) / i;
        Noise.a += abs(noise((Pos + 3) * 500 * i)) / i;
    }

    return Noise;
}

// function used to fill the sin LUT texture
float4 GenerateSinFunction(float3 Pos : POSITION) : COLOR
{
    return sin( Pos.x * rm_PI * 2.0 );
}

// function used to fill the specular power LUT texture
float4 GeneratePowFunction(float3 Pos : POSITION) : COLOR
{
    return pow( Pos.x, 16.0 );
}

// function used to fill the "Linear LUT" texture
float4 GenerateLinearFunction(float2 Pos : POSITION) : COLOR
{
    return float4(Pos, Pos);
}

//
// Blinn lighting shader
//

struct PS_INPUTBLINN
{
    rm_float2 vTexCoord : TEXCOORD0;
    rm_float3 vTangent  : TEXCOORD1;
    rm_float3 vBinormal : TEXCOORD2;
    rm_float3 vNormal   : TEXCOORD3;
    rm_float3 vEye      : TEXCOORD4;
    rm_float4 vLight    : TEXCOORD5;
};

rm_float4 PSBlinn ( PS_INPUTBLINN In ) : COLOR
{
	// Bump Mapping

	rm_float2 vBump = tex2D( NormalMapSampler, In.vTexCoord );

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 vN = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 vN = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#else 
	rm_float3 vN = normalize( In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#endif
	// Lighting

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 vE = texCUBE( NormalizationCubeMapSampler, In.vEye ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 vE = texCUBE( NormalizationCubeMapSampler, In.vEye );
#else
	rm_float3 vE = normalize( In.vEye );
#endif
	rm_float4 vLight = In.vLight / sqrt( dot( In.vLight.xyz, In.vLight.xyz ) );

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 vH = texCUBE( NormalizationCubeMapSampler, vE.xyz + vLight.xyz ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 vH = texCUBE( NormalizationCubeMapSampler, vE.xyz + vLight.xyz );
#else
	rm_float3 vH = normalize( vE.xyz + vLight.xyz );
#endif
	rm_float fNdotL = saturate( dot( vN.xyz, vLight.xyz ) );
	rm_float fNdotH = saturate( dot( vN.xyz, vH.xyz ) );

#if POW_LUT
	rm_float fSpec = tex2D( PowSampler, fNdotH );
#else
	rm_float fSpec = pow( fNdotH, fMaterialPower );
#endif
        rm_float4 vDiffuse  = Lights[0].vDiffuse * fNdotL;
	rm_float4 vSpecular = Lights[0].vSpecular * fSpec;
	
	// Finalize

	return ( vDiffuse * tex2D( DiffuseMapSampler, In.vTexCoord ) +
	         vSpecular * tex2D( SpecularMapSampler, In.vTexCoord ) ) * vLight.w;
}

struct VS_OUTPUTBLINN
{
    rm_float4 vPosition : POSITION;

    rm_float2 vTexCoord : TEXCOORD0;
    rm_float3 vTangent  : TEXCOORD1;
    rm_float3 vBinormal : TEXCOORD2;
    rm_float3 vNormal   : TEXCOORD3;
    rm_float3 vEye      : TEXCOORD4;
    rm_float4 vLight    : TEXCOORD5;
};

VS_OUTPUTBLINN VSBlinn( rm_float4 vPosition : POSITION,
    		        rm_float4 vNormal   : NORMAL,
		        rm_float2 vTexCoord : TEXCOORD0,
		        rm_float3 vTangent  : TEXCOORD1,
		        rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUTBLINN o;

	// Position

	o.vPosition = mul( vPosition, mWVP );

	// Texture Coords

	o.vTexCoord.xy  = vTexCoord.xy;

	// Tangent Space

	o.vTangent  = mul( vTangent.xyz,  mW );
	o.vBinormal = mul( vBinormal.xyz, mW );
	o.vNormal   = mul( vNormal.xyz,   mW );

	// Vertexl Position -> World Space

	rm_float4 vPositionWorld = mul( vPosition, mW ) * fGeometryScale;

	// Eye Vector

	o.vEye = vCameraPos.xyz - vPositionWorld.xyz;

	// Light Vector 

	o.vLight.xyz   = Lights[0].vPosition.xyz - vPositionWorld.xyz;
	o.vLight.w     = Lights[0].fAttenuation;

	// Finalize

	return o;
}

//
// Phong lighting shader
//

struct PS_INPUT
{
    rm_float2 vTexCoord    : TEXCOORD0;
    rm_float3 vTangent     : TEXCOORD1;
    rm_float3 vBinormal    : TEXCOORD2;
    rm_float3 vNormal      : TEXCOORD3;
    rm_float3 vEye         : TEXCOORD4;
    rm_float4 vLights[3]   : TEXCOORD5;
};

rm_float4 PSPhong ( PS_INPUT In, uniform int nNumLights ) : COLOR
{
	// Bump Mapping

	rm_float2 vBump = tex2D( NormalMapSampler, In.vTexCoord );

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 vN = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 vN = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#else 
	rm_float3 vN = normalize( In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#endif
	// Lighting

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 vE = texCUBE( NormalizationCubeMapSampler, In.vEye ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 vE = texCUBE( NormalizationCubeMapSampler, In.vEye );
#else
	rm_float3 vE = normalize( In.vEye );
#endif
	rm_float3 vR = reflect( vE, vN );

        rm_float4 vDiffuse  = 0.0;
        rm_float4 vSpecular = 0.0;

        for( int i = 0; i < nNumLights; i++ ) 
        { 
	        rm_float4 vLight; 
		rm_float  fNdotL;
		rm_float2 fRdotE;
		rm_float  fSpec;

                vLight     = In.vLights[i] / sqrt( dot( In.vLights[i].xyz, In.vLights[i].xyz ) );
                fNdotL     = saturate( dot( vLight.xyz, vN.xyz ) );

		fRdotE     = saturate( dot( vR.xyz, -vLight.xyz ) );
#if POW_LUT
		fSpec      = tex2D( PowSampler, fRdotE );
#else
		fSpec      = pow( fRdotE, fMaterialPower );
#endif
                vDiffuse  += (Lights[i].vDiffuse * fNdotL) * vLight.w;
		vSpecular += (Lights[i].vSpecular * fSpec) * vLight.w;

        } 
	
	// Finalize

	return vDiffuse * tex2D( DiffuseMapSampler, In.vTexCoord ) +
	       vSpecular * tex2D( SpecularMapSampler, In.vTexCoord );
}

struct VS_OUTPUT
{
    rm_float4 vPosition    : POSITION;

    rm_float2 vTexCoord    : TEXCOORD0;
    rm_float3 vTangent     : TEXCOORD1;
    rm_float3 vBinormal    : TEXCOORD2;
    rm_float3 vNormal      : TEXCOORD3;
    rm_float3 vEye         : TEXCOORD4;
    rm_float4 vLights[3]   : TEXCOORD5;
};

VS_OUTPUT VSPhong( rm_float4 vPosition : POSITION,
    		   rm_float4 vNormal   : NORMAL,
		   rm_float2 vTexCoord : TEXCOORD0,
		   rm_float3 vTangent  : TEXCOORD1,
		   rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUT o;

	// Position

	o.vPosition = mul( vPosition, mWVP );

	// Texture Coords

	o.vTexCoord.xy  = vTexCoord.xy;

	// Tangent Space

	o.vTangent  = mul( vTangent.xyz,  mW );
	o.vBinormal = mul( vBinormal.xyz, mW );
	o.vNormal   = mul( vNormal.xyz,   mW );

	// Vertexl Position -> World Space

	rm_float4 vPositionWorld = mul( vPosition, mW ) * fGeometryScale;

	// Eye Vector

	o.vEye = vCameraPos.xyz - vPositionWorld.xyz;

	// Light Vector 

	for( int i = 0; i < 3; i++ )
	{
		o.vLights[i].xyz   = Lights[i].vPosition.xyz - vPositionWorld.xyz;
		o.vLights[i].w     = Lights[i].fAttenuation;
	}

	// Finalize

	return o;
}

//
// Cook-Torrance lighting shader ( based on nVidia's Surface Reflection Shader demo effect )
//

float m = 0.12f; // The RMS slope of the microfacets (large m = more spread out reflection)
float n = 1.45f; // The index of refraction

#define PI 3.14159265358979

rm_float4 PSCookTorrance ( PS_INPUT In, uniform int nNumLights ) : COLOR
{
	// Bump Mapping

	rm_float2 vBump = tex2D( NormalMapSampler, In.vTexCoord );

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 N = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 N = texCUBE( NormalizationCubeMapSampler, In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#else 
	rm_float3 N = normalize( In.vNormal + vBump.x * In.vTangent + vBump.y * In.vBinormal );
#endif

	// Lighting

#if NORMALIZATION_CUBEMAP_A8R8G8B8
	rm_float3 E = texCUBE( NormalizationCubeMapSampler, In.vEye ) * 2.0 - 1.0;
#elif NORMALIZATION_CUBEMAP_Q8W8V8U8
	rm_float3 E = texCUBE( NormalizationCubeMapSampler, In.vEye );
#else
	rm_float3 E = normalize( In.vEye );
#endif

        rm_float4 vDiffuse  = 0.0;
        rm_float4 vSpecular = 0.0;

        for( int i = 0; i < nNumLights; i++ ) 
        { 
		// Calculate the light vector

		rm_float3 L = In.vLights[i] / sqrt( dot( In.vLights[i].xyz, In.vLights[i].xyz ) );

		// Calculate the H vector

		rm_float3 H = normalize(L+E);
    
	        // calculate all the dot products

	        rm_float NdotH = dot(N, H);
        	rm_float EdotH = dot(E, H);
	        rm_float LdotH = dot(L, H);
        	rm_float NdotL = dot(N, L);
	        rm_float NdotE = dot(N, E);

	        // calculate the G term ( Self shadowing term )

	        rm_float Gcommon    = ( 2.0 * NdotH ) / EdotH;
        	rm_float Gmasking   = Gcommon * NdotE;
	        rm_float Gshadowing = Gcommon * NdotL;
	        rm_float G = min( min( 1, Gmasking ), Gshadowing );

	        // calculate the F term ( Fresnel term "Schlick's approximation" )

	        rm_float F = 1.0 - NdotE;
        	F = pow( F, 5.0 );
	        F = lerp(F, 1.0, n);
    
	  	// calculate the D term ( Beckmann's distribution function )
        	// note that B = angle between N and H (ie acos(NdotH))

	        rm_float sinB = length( cross(N, H) );
        	rm_float cosB = NdotH;

	        float exponent = ( sinB / cosB ) / m;
        	exponent = exponent * exponent;

	        rm_float cosTerm = NdotH;
        	cosTerm = cosTerm * cosTerm;
	        cosTerm = cosTerm * cosTerm;        

		rm_float D = exp( -exponent ) / ( 4.0 * m * m * cosTerm );

       		// create an intermediate term DGF

        	rm_float DGF = D * G * F;

	        // calculate p

		rm_float p = DGF / ( PI * NdotE * NdotL );

	        // calculate the I term

		vDiffuse  += ( 0.005 * Lights[i].vDiffuse + p ) * max( 0.0, NdotL ); 
        	vSpecular += max( 0.0, ( 0.005 * Lights[i].vSpecular * DGF ) / ( PI * NdotE ) );
        } 
	
	// Finalize

	return vDiffuse * tex2D( DiffuseMapSampler, In.vTexCoord ) +
	       vSpecular * tex2D( SpecularMapSampler, In.vTexCoord );
}

//
// Psycodelic shader ( based on John Spitzer's Real-Time Procedural Effects presentation, marble shader, 
//                     and ATI's marble shader from RenderMonkey  )
//

rm_float4 Psycodelic( rm_float3 pfreq1 : TEXCOORD0,
                      rm_float3 pfreq2 : TEXCOORD1,
                      rm_float3 pfreq3 : TEXCOORD2,
                      rm_float3 pfreq4 : TEXCOORD3,
	              rm_float2 pfreq5 : TEXCOORD4 ) : COLOR
{
   float marble  = abs(tex3D( NoiseSampler, pfreq3 ) - 0.5 )
		   + tex3D( NoiseSampler, pfreq2 );

   return marble * tex3D( NoiseSampler, pfreq2 ) + tex3D( NoiseSampler, pfreq1 );
}

struct VS_OUTPUTPSYCHODELIC 
{
    rm_float4 vPosition    : POSITION;

    rm_float3 pfreq1       : TEXCOORD0;
    rm_float3 pfreq2       : TEXCOORD1;
    rm_float3 pfreq3       : TEXCOORD2;
    rm_float3 pfreq4       : TEXCOORD3;
    rm_float2 pfreq5       : TEXCOORD4;
};

VS_OUTPUTPSYCHODELIC VSPsychodelic( rm_float4 vPosition : POSITION,
    		                    rm_float4 vNormal   : NORMAL,
		                    rm_float2 vTexCoord : TEXCOORD0,
		                    rm_float3 vTangent  : TEXCOORD1,
		                    rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUTPSYCHODELIC o;

	// Position

	o.vPosition = mul( vPosition, mWVP );

	// Apply a texture matrix here if desired.
	// shift by time?

	rm_float3 vTemp = vPosition.xyz;
        vTemp.xyz -= vTime.y * 0.005;
	
	// position at freqeuncy 1 and 5

	vTemp.xyz *= fInitFreq;
	o.pfreq1.xyz = vTemp.xyz;
	o.pfreq5.xy = o.pfreq1.xy * fFactor;

	// position at freqeuncy 2

	vTemp.xyz *= fFreqScale;
	o.pfreq2.xyz = vTemp.xyz;

	// position at freqeuncy 3

	vTemp.xyz *= fFreqScale;
	o.pfreq3.xyz = vTemp.xyz;

	// position at freqeuncy 4

	o.pfreq4.xyz = vTemp.xyz * fFreqScale;

	// Finalize

	return o;
}

//
// Wood shader ( based on Microsoft's DirectX SDK 9.0 EffectEdit demo (wood shader) )
//

#define DARK_COLOR  0.3
#define LIGHT_COLOR 1.0

rm_float4 WoodColor = { 1.0, 0.7, 0.2, 1.0 };

rm_float4 Wood( rm_float2 Tex0 : TEXCOORD0,
                rm_float3 Tex1 : TEXCOORD1 ) : COLOR
{
    rm_float Wood = tex2D(LinearSampler, Tex0) +  0.05 * ( tex3D( NoiseSampler, Tex1 ) - 0.5 ); 
    Wood += 10.0 * tex3D( NoiseSampler, Wood );

    return WoodColor * lerp( 0.3, 1.0, saturate( 0.8 - 0.6 * Wood ) );
}

struct VS_OUTPUTWOOD
{
    rm_float4 vPosition    : POSITION;

    rm_float2 vTex0      : TEXCOORD0;
    rm_float3 vTex1      : TEXCOORD1;
};

VS_OUTPUTWOOD VSWood( rm_float4 vPosition : POSITION,
    		      rm_float4 vNormal   : NORMAL,
		      rm_float2 vTexCoord : TEXCOORD0,
		      rm_float3 vTangent  : TEXCOORD1,
		      rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUTWOOD o;

	// Position

	o.vPosition = mul( vPosition, mWVP );

        o.vTex1 = 0.04 * vPosition; 
        o.vTex0 = 25.0 * length( o.vTex1.xz );

	// Finalize

	return o;
}

//
// Marble Shader ( based on nVidia's marble shader )
//

rm_float4 Marble( rm_float3 pfreq1 : TEXCOORD0,
                  rm_float3 pfreq2 : TEXCOORD1,
                  rm_float3 pfreq3 : TEXCOORD2,
                  rm_float3 pfreq4 : TEXCOORD3,
		  rm_float2 pfreq5 : TEXCOORD4 ) : COLOR
{
    rm_float2 turb  = 0.5 * tex3D( NoiseSampler, pfreq1 );
              turb += 0.25 * tex3D( NoiseSampler, pfreq2 );
              turb += 0.125 * tex3D( NoiseSampler, pfreq3 );
              turb += 0.06125 * tex3D( NoiseSampler, pfreq4 );
#if SINUS_LUT
    turb = tex2D( SinSampler, fScale * turb + pfreq5 );
#else
    turb = sin( fScale * turb + pfreq5 );
#endif

    return tex2D( MarbleSampler, turb );
}

struct VS_OUTPUTMARBLE
{
    rm_float4 vPosition    : POSITION;

    rm_float3 pfreq1       : TEXCOORD0;
    rm_float3 pfreq2       : TEXCOORD1;
    rm_float3 pfreq3       : TEXCOORD2;
    rm_float3 pfreq4       : TEXCOORD3;
    rm_float2 pfreq5       : TEXCOORD4;
};

VS_OUTPUTMARBLE VSMarble( rm_float4 vPosition : POSITION,
    		          rm_float4 vNormal   : NORMAL,
		          rm_float2 vTexCoord : TEXCOORD0,
		          rm_float3 vTangent  : TEXCOORD1,
		          rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUTMARBLE o;

	// Position

	o.vPosition = mul( vPosition, mWVP );

	// Apply a texture matrix here if desired.
	// shift by time?

	rm_float3 vTemp = vPosition.xyz;
        vTemp.xyz -= vTime.y * 0.01;

	// position at freqeuncy 1

	vTemp.xyz *= fInitFreq;
	o.pfreq1.xyz = vTemp.xyz;

	// position at freqeuncy 5

	rm_float3 vTemp1 = vPosition.xyz;
        vTemp1.y -= vTime.y * 0.01;
	vTemp1.xyz *= fInitFreq;
	
	o.pfreq5.xy = vTemp1.xy * fFactor;

	// position at freqeuncy 2

	vTemp.xyz *= fFreqScale;
	o.pfreq2.xyz = vTemp.xyz;

	// position at freqeuncy 3

	vTemp.xyz *= fFreqScale;
	o.pfreq3.xyz = vTemp.xyz;

	// position at freqeuncy 4

	o.pfreq4.xyz = vTemp.xyz * fFreqScale;

	// Finalize

	return o;
}

//
// Water Shader ( based on Smoke material from Discreet's 3D Studio Max )
//

float4 vWaterColor = { 0.2, 0.2, 0.5, 1 };

float4 Water( rm_float3 vPosition : TEXCOORD0 ) : COLOR
{


	float mag = 0.0;
	float   s = 1.0;
	float3  r = vPosition; 

	for( int i = 0; i < 20; i++ ) 
	{
		r.x += 0.03 * tex3D( NoiseSampler, r );
		r.y += 0.03 * tex3D( NoiseSampler, r );
		r.z += 0.03 * tex3D( NoiseSampler, r );

		float tex = tex3D( NoiseSampler, r );

		mag += tex / s;

		r *= 2.0;
		s *= 2.0;
	}

	float fWater = saturate( 0.5 * pow( mag, 1.5 ) );

	return lerp( vWaterColor, 1, fWater );

}

struct VS_OUTPUTWATER
{
    rm_float4 vPosition    : POSITION;
    rm_float3 vVertexPos   : TEXCOORD0;
};

VS_OUTPUTWATER VSWater( rm_float4 vPosition : POSITION,
    		        rm_float4 vNormal   : NORMAL,
		        rm_float2 vTexCoord : TEXCOORD0,
		        rm_float3 vTangent  : TEXCOORD1,
		        rm_float3 vBinormal : TEXCOORD2 )
{
	VS_OUTPUTWATER o;

	// Position

	o.vPosition = mul( vPosition, mWVP );
	o.vVertexPos.xyz = 0.0005 * vPosition.xyz + 0.00001 * vTime.y;

	// Finalize

	return o;
}

PixelShader psArray[7] = 
{ 
        compile ps_1_1 Psycodelic(),
        compile ps_1_4 Wood(),
        compile ps_2_0 Marble(),
        compile ps_2_a Water(),
        compile ps_2_0 PSBlinn(),
        compile ps_2_0 PSPhong(3), 
        compile ps_2_a PSCookTorrance(3), 
}; 

VertexShader vsArray[7] = 
{ 
        compile vs_1_1 VSPsychodelic(),
        compile vs_1_1 VSWood(),
        compile vs_2_0 VSMarble(), 
	compile vs_2_a VSWater(), 
        compile vs_2_0 VSBlinn(),
        compile vs_2_0 VSPhong(),
        compile vs_2_a VSPhong(),
}; 

//
// Default Technique
//

technique TDefault
{   
	pass p0
	{
		// Common States

		// CullMode	    = CCW;
		// AlphaBlendEnable = False;
	        // ZEnable          = True;
       		// ZWriteEnable     = True;

		// Shaders

		PixelShader = ( psArray[nPixelShader] );
		VertexShader = ( vsArray[nVertexShader] );
	}
}