/*******************************************************************
*	CelShader.fx
*	Author - Pongthep Charnchaichujit
*	Created on - ?
*
*   All content © 2007 - 2008 DigiPen (USA) Corporation, all rights reserved.
*******************************************************************/
#include "Scene.h"

//CONSTANTS
float4x4 World;
float4x4 WorldViewProjection;
float4x4 View;
float4x4 ViewProjMatrix;
float3 Eye;
float time;
float randSeed;
float fRadius;

//shadow
texture ShadowMapTex;
float shadowScale = 0.1;

//Color
float4 DiffuseColor;
texture DiffuseTex;
texture BumpTex;

float AmbientCoef = 0.2f;
float DiffuseCoef = 0.8f;
float SpecularPower = 20.0f;

// Settings controlling the Toon lighting technique.
float ToonThresholds[2] = { 0.8, 0.4 };
float ToonBrightnessLevels[3] = { 1.3, 0.9, 0.5 };

//STRUCTS
struct VS_IN {
	float4 pos : POSITION;
	float2 tex : TEXCOORD;
	float4 normal : NORMAL;
	float4 tangent : TANGENT;
	float4 biNormal : BINORMAL;
};

struct PS_IN {
	float4 pos : POSITION;
	float2 tex : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float4 wpos : TEXCOORD2;
	float3 vpos : TEXCOORD3;
};

sampler ShadowSampler = sampler_state
{
	texture = <ShadowMapTex>;
};

//diffuse texture sampler
sampler DiffuseSampler = sampler_state 
{
	texture = <DiffuseTex>;
	AddressU  = WRAP;
	AddressV  = WRAP;
	AddressW  = WRAP;
	//MIPFILTER = LINEAR;
	MINFILTER = LINEAR;
	MAGFILTER = LINEAR;
};

sampler BumpSampler = sampler_state 
{
	texture = <BumpTex>;
	AddressU  = WRAP;
	AddressV  = WRAP;
	AddressW  = WRAP;
	//MIPFILTER = LINEAR;
	MINFILTER = LINEAR;
	MAGFILTER = LINEAR;
};

/*********************************************************
****				VERTEX&PIXEL SHADER					**
*********************************************************/

PS_IN BlobShaderColorVertexShader(VS_IN input)
{
	PS_IN Out;

	const float TWO_PI = 6.2831853072;

	const float4 wave_directions_in_X	= {1, 2, 0, 4};		// relative to u
	const float4 wave_directions_in_Y	= {2, 1, 4, 0};		// relative to v

	const float4 waveSpeed			= {0.5, -0.5, 0.5, -0.5};
	const float4 waveHeights 		= {0.25 , 0.25 , 0.5 , 0.5};

	// use texture coordinates as inputs to sinusoidal warp
	float4 wave_vec = frac(	wave_directions_in_X*input.tex.x +
							wave_directions_in_Y*input.tex.y + waveSpeed*time );

   	// shift the texture coordinates to be in (pi, -pi) range
   	wave_vec = (wave_vec - 0.5) * TWO_PI;

   	float4 wave_vec_sin = sin(wave_vec);
   	float4 wave_vec_cos = (2 - cos(wave_vec))*0.04;		// multiply by 0.04 as fix up factor

	// dot with waveHeights and then apply deformation in the direction of the normal
	wave_vec = dot(wave_vec_sin,waveHeights) * input.normal + input.pos;
	wave_vec.w = 1; 	// homogeneous component

	// transform wave vector 
	Out.pos = mul(wave_vec, WorldViewProjection);

	// compute the binomial
	float4 binomial = float4(cross(input.tangent.xyz, input.normal.xyz), 1);

	// warp normal based on tangent and binomial vectors
	float4 warpedNormal = input.tangent  * dot(-(wave_vec_cos * waveHeights), wave_directions_in_Y) +
					binomial * dot(-(wave_vec_cos * waveHeights), wave_directions_in_X);
	warpedNormal = warpedNormal + input.normal;

	// transform and normalize the normal
	warpedNormal = normalize(mul(World, warpedNormal));
	
	// compute a normalized view vector
	float4 cameraPos = {Eye.x, Eye.y, Eye.z, 0.0};
	float4 viewVector = normalize(cameraPos - mul(World, wave_vec));
	
	// pass along texture coordinates
	Out.tex = input.tex;
	Out.wpos = mul(input.pos, World);
	Out.vpos = mul(Out.wpos, View);
	float3 normal1 = {input.normal.x, input.normal.y, input.normal.z};
	Out.normal = mul(normal1, (float3x3)World);

	return Out;
}


float4 BlobShaderColorPixelShader(PS_IN input) : COLOR
{
	float3 normal = normalize(input.normal);
	float3 view_dir = normalize((float3)input.wpos - Eye);
	float3 light_dir;
	float diffuse, diffuse_light = 0;
	
	float4 col = 0;
	float4 bumpSpec = 0;
	float3 vVec = normalize(view_dir);
	float3 bump = normalize(  (tex2D(BumpSampler, input.tex).xyz * 2.0) - 1.0);

	for (int i=0; i<numLights; i++)
	{
		light_dir = normalize(Lights[i] - (float3)input.wpos);
		
		diffuse = saturate(dot(normal, light_dir));
		
		if (diffuse > ToonThresholds[0])
		{
			diffuse_light += ToonBrightnessLevels[0];
		}
		else if (diffuse > ToonThresholds[1])
		{
			diffuse_light += ToonBrightnessLevels[1];
		}
		else
		{
			diffuse_light += ToonBrightnessLevels[2];
		}

		bumpSpec += pow(clamp(dot(reflect(-light_dir, bump), vVec), 0.0, 1.0), 30);
	}
	diffuse_light /= numLights;
	col = float4(DiffuseColor.xyz * diffuse_light, 1);
	
	float4 baseColor = float4(DiffuseColor.xyz,1);

	float biggestDif = 0;
	biggestDif = max(abs(baseColor.x-baseColor.y),biggestDif);
	biggestDif = max(abs(baseColor.y-baseColor.z),biggestDif);
	biggestDif = max(abs(baseColor.z-baseColor.x),biggestDif);

	col += bumpSpec * biggestDif * 0.1;
	col.a = 1.f;

	return col;
}

technique BlobShaderColor
{
	pass P0
	{
		VertexShader = compile vs_2_a BlobShaderColorVertexShader();
		PixelShader = compile ps_2_a BlobShaderColorPixelShader();
	}
}
