//-----------------------------------------------------------------------------
// shader
//-----------------------------------------------------------------------------

#define Z_SHIFT 0.005f

float4x4 WorldViewProjectionMatrix;
float4x4 WorldMatrix;
float3 LocalLightVector;
float Ambient;
float4 Color;					// material color * light color
float3 LocalCameraPos;
float3 WorldCameraPos;
float Specular;
int SpecularPow;
float Reflection;
float4x4 TreeMatrix;
float TreeRadius, TreeColor;

float PixelSize;
float SpringPower;
float2 AddWavePos;
float AddWaveSpeed;

float FrameTime;		// not used

sampler tex0 : register(s0);

// for shadow map
float4x4 LightWorldViewProjectionMatrix;
float BlurU[5];
float BlurV[5];

texture DiffuseTex;
sampler DiffuseSamper = sampler_state
{
	Texture = <DiffuseTex>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR; 
	MipMapLodBias = -2;

	AddressU = WRAP;
	AddressV = WRAP;
};

texture NormalTex;
sampler NormalSamper = sampler_state
{
	Texture = <NormalTex>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR; 
	MipMapLodBias = -2;

	AddressU = WRAP;
	AddressV = WRAP;
};

textureCUBE CubeTex;
samplerCUBE CubeTexSampler = sampler_state
{ 
	Texture = <CubeTex>; 
	MinFilter = LINEAR; 
	MagFilter = LINEAR; 
	MipFilter = LINEAR; 
}; 

texture ShadowMapTex;
sampler ShadowMapSampler = sampler_state
{
    texture = <ShadowMapTex>;
    AddressU  = CLAMP;        
    AddressV  = CLAMP;
    AddressW = CLAMP;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
};

//-----------------------------------------------------------------------------

struct VS_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 localLightVector : TEXCOORD2;
	float3 localCameraVector : TEXCOORD3;   // -(camera to point)
}; 

VS_OUT VS(float4 pos : POSITION, float3 normal: NORMAL, float2 texcoord : TEXCOORD)
{ 
	VS_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	Out.normal = normalize(normal);
	Out.localLightVector = LocalLightVector;
	Out.localCameraVector = normalize(LocalCameraPos-pos.xyz);

	return Out; 
} 

float4 PS(VS_OUT In) : COLOR
{ 
	float4 color = Color*max(Ambient, dot(In.normal, In.localLightVector))
		+Specular*pow(max(0.0f, dot(In.normal, normalize(In.localLightVector+In.localCameraVector))), SpecularPow);

	color.a = 1.0f;	

	return color*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_ENV_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 localLightVector : TEXCOORD2;
	float3 localCameraVector : TEXCOORD3;   // -(camera to point)
	
	float3 WorldNormal : TEXCOORD4;
	float3 WorldCameraVector : TEXCOORD5;
}; 

VS_ENV_OUT VS_ENV(float4 pos : POSITION, float3 normal: NORMAL, float2 texcoord : TEXCOORD)
{ 
	VS_ENV_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	Out.normal = normal;
	Out.localLightVector = LocalLightVector;
	Out.localCameraVector = normalize(LocalCameraPos-pos.xyz);

	Out.WorldNormal = mul(normal, (float3x3)WorldMatrix);
	Out.WorldCameraVector = (float3)mul(pos, WorldMatrix)-WorldCameraPos;

	return Out; 
} 

float4 PS_ENV(VS_ENV_OUT In) : COLOR
{ 
	float4 color = Color*max(Ambient, dot(In.normal, In.localLightVector))
		+Specular*pow(max(0.0f, dot(In.normal, normalize(In.localLightVector+In.localCameraVector))), SpecularPow);

	color.a = 1.0f;	

	return color*tex2D(DiffuseSamper, In.texcoord)
		+texCUBE(CubeTexSampler, reflect(In.WorldCameraVector, In.WorldNormal))*Reflection;		// environmental color
}

//-----------------------------------------------------------------------------

struct VS_BUMP_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
	float3 localLightVector : TEXCOORD1;
	float3 halfVector : TEXCOORD2;
};

VS_BUMP_OUT VS_BUMP(float4 pos : POSITION, float3 tangent : TANGENT, float3 binormal : BINORMAL,
	float3 normal : NORMAL, float2 texcoord : TEXCOORD0)
{
	VS_BUMP_OUT Out;
	
	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord;

	// convert to the pixel coordinate
	Out.localLightVector.x = dot(LocalLightVector, tangent);
	Out.localLightVector.y = dot(LocalLightVector, binormal);
	Out.localLightVector.z = dot(LocalLightVector, normal);
	
	float3 halfVector = normalize(LocalLightVector+normalize(LocalCameraPos-pos.xyz));
		
	Out.halfVector.x = dot(halfVector, tangent);
	Out.halfVector.y = dot(halfVector, binormal);
	Out.halfVector.z = dot(halfVector, normal);
	
	return Out;
}

float4 PS_BUMP(VS_BUMP_OUT In) : COLOR
{   
    float3 normal = normalize(tex2D(NormalSamper, In.texcoord).rgb*2.0f-1.0f);
    
	float4 color = Color*max(Ambient, dot(normal, In.localLightVector))
		+Specular*pow(max(0.0f, dot(normal, normalize(In.halfVector))), SpecularPow);				// phong (pow = 80)

	color.a = 1.0f;	

	return color*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_MAKE_SHADOW_OUT
{
	float4 pos : POSITION;
	float2 shadowMapTexcoord : TEXCOORD;
};

VS_MAKE_SHADOW_OUT VS_MAKE_SHADOW(float4 pos : POSITION)
{
	VS_MAKE_SHADOW_OUT Out;

	Out.pos = mul(pos, LightWorldViewProjectionMatrix);
	Out.shadowMapTexcoord.xy = Out.pos.zw;

	return Out;
}

float4 PS_MAKE_SHADOW(VS_MAKE_SHADOW_OUT In) : COLOR
{
	float4 Out;

	Out.rgb = In.shadowMapTexcoord.x/In.shadowMapTexcoord.y;
	Out.a = 1.0f;

	return Out;
}

//-----------------------------------------------------------------------------

struct VS_MAKE_SHADOW_TEX_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
	float2 shadowMapTexcoord : TEXCOORD1;
};

VS_MAKE_SHADOW_TEX_OUT VS_MAKE_SHADOW_TEX(float4 pos : POSITION, float2 texcoord : TEXCOORD0)
{
	VS_MAKE_SHADOW_TEX_OUT Out;

	Out.pos = mul(pos, LightWorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	Out.shadowMapTexcoord.xy = Out.pos.zw;

	return Out;
}

float4 PS_MAKE_SHADOW_TEX(VS_MAKE_SHADOW_TEX_OUT In) : COLOR
{
	float4 Out;

	Out.rgb = In.shadowMapTexcoord.x/In.shadowMapTexcoord.y;
	Out.a = tex2D(DiffuseSamper, In.texcoord).a;

	return Out;
}

//-----------------------------------------------------------------------------

struct VS_SHADOW_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 localLightVector : TEXCOORD2;
	float3 localCameraVector : TEXCOORD3;   // -(camera to point)

	float4 shadowMapTexcoord : TEXCOORD4;
}; 

VS_SHADOW_OUT VS_SHADOW(float4 pos : POSITION, float3 normal: NORMAL, float2 texcoord : TEXCOORD)
{ 
	VS_SHADOW_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	Out.normal = normalize(normal);
	Out.localLightVector = LocalLightVector;
	Out.localCameraVector = normalize(LocalCameraPos-pos.xyz);
	
//	Out.shadowMapTexcoord = Out.pos;
	Out.shadowMapTexcoord = mul(pos, LightWorldViewProjectionMatrix);

	return Out; 
} 

float4 PS_SHADOW(VS_SHADOW_OUT In) : COLOR
{ 
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float4 color = Color;
	if (In.shadowMapTexcoord.z/In.shadowMapTexcoord.w > tex2D(ShadowMapSampler, texcoord).x+Z_SHIFT) color *= 0.85f; 

	float4 color2 = color*max(Ambient, dot(In.normal, In.localLightVector))
		+Specular*pow(max(0.0f, dot(In.normal, normalize(In.localLightVector+In.localCameraVector))), SpecularPow);

	color2.a = 1.0f;	

	return color2*tex2D(DiffuseSamper, In.texcoord);

//	float shadow = tex2D(ShadowMapSampler, texcoord).r;
	
//	float4 color2 = Color*max(Ambient, shadow*dot(In.normal, In.localLightVector))
//		+Specular*shadow*pow(max(0.0f, dot(In.normal, normalize(In.localLightVector+In.localCameraVector))), SpecularPow);

//	color2.a = 1.0f;	

//	return color2*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_SHADOW_ENV_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 localLightVector : TEXCOORD2;
	float3 localCameraVector : TEXCOORD3;   // -(camera to point)
	
	float3 WorldNormal : TEXCOORD4;
	float3 WorldCameraVector : TEXCOORD5;

	float4 shadowMapTexcoord : TEXCOORD6;
}; 

VS_SHADOW_ENV_OUT VS_SHADOW_ENV(float4 pos : POSITION, float3 normal: NORMAL, float2 texcoord : TEXCOORD)
{ 
	VS_SHADOW_ENV_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	Out.normal = normal;
	Out.localLightVector = LocalLightVector;
	Out.localCameraVector = normalize(LocalCameraPos-pos.xyz);

	Out.WorldNormal = mul(normal, (float3x3)WorldMatrix);
	Out.WorldCameraVector = mul(pos, WorldMatrix).xyz-WorldCameraPos;

	Out.shadowMapTexcoord = Out.pos;

	return Out; 
} 

float4 PS_SHADOW_ENV(VS_SHADOW_ENV_OUT In) : COLOR
{ 
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float shadow = tex2D(ShadowMapSampler, texcoord).r;
//	shadow = max(Ambient, shadow*shadow);
	
	float4 color2 = Color*max(Ambient, shadow*dot(In.normal, In.localLightVector))
		+Specular*shadow*pow(max(0.0f, dot(In.normal, normalize(In.localLightVector+In.localCameraVector))), SpecularPow);

	color2.a = 1.0f;	

	return color2*tex2D(DiffuseSamper, In.texcoord)+texCUBE(CubeTexSampler, reflect(In.WorldCameraVector, In.WorldNormal))*Reflection;		// environmental color
}

//-----------------------------------------------------------------------------

struct VS_SHADOW_BUMP_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
	float3 localLightVector : TEXCOORD1;
	float3 halfVector : TEXCOORD2;

	float4 shadowMapTexcoord : TEXCOORD3;
};

VS_SHADOW_BUMP_OUT VS_SHADOW_BUMP(float4 pos : POSITION, float3 tangent : TANGENT, float3 binormal : BINORMAL,
	float3 normal : NORMAL, float2 texcoord : TEXCOORD0)
{
	VS_SHADOW_BUMP_OUT Out;
	
	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord;

	Out.localLightVector.x = dot(LocalLightVector, tangent);
	Out.localLightVector.y = dot(LocalLightVector, binormal);
	Out.localLightVector.z = dot(LocalLightVector, normal);

	float3 halfVector = normalize(LocalLightVector+normalize(LocalCameraPos-pos.xyz));
		
	Out.halfVector.x = dot(halfVector, tangent);
	Out.halfVector.y = dot(halfVector, binormal);
	Out.halfVector.z = dot(halfVector, normal);

	Out.shadowMapTexcoord = Out.pos;
	
	return Out;
}

float4 PS_SHADOW_BUMP(VS_SHADOW_BUMP_OUT In) : COLOR
{   
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
    float3 normal = normalize(tex2D(NormalSamper, In.texcoord).rgb*2.0f-1.0f);
    
	float shadow = tex2D(ShadowMapSampler, texcoord).r;
//	shadow = max(Ambient, shadow*shadow);

	float4 color2 = Color*max(Ambient, shadow*dot(normal, In.localLightVector))
		+Specular*shadow*pow(max(0.0f, dot(normal, normalize(In.halfVector))), SpecularPow);				// phong (pow = 80)

	color2.a = 1.0f;	

	return color2*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_TREE_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float4 color : COLOR;
}; 

VS_TREE_OUT VS_TREE(float4 pos : POSITION, float2 texcoord : TEXCOORD)
{ 
	VS_TREE_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	
	float4 pos2 = mul(pos, TreeMatrix);
	float shift = TreeColor+(-pos2.x+pos2.y-pos2.z)/TreeRadius;
	shift = saturate(shift);

//shift = 1.0f;

	Out.color.r = shift;
	Out.color.g = shift;
	Out.color.b = shift;
	Out.color.a = 1.0f;

	return Out; 
} 

float4 PS_TREE(VS_TREE_OUT In) : COLOR
{ 
	return In.color*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_SHADOW_TREE_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;
	float4 color : COLOR;

	float4 shadowMapTexcoord : TEXCOORD1;
}; 

VS_SHADOW_TREE_OUT VS_SHADOW_TREE(float4 pos : POSITION, float2 texcoord : TEXCOORD)
{ 
	VS_SHADOW_TREE_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 
	
	float4 pos2 = mul(pos, TreeMatrix);
	float shift = TreeColor+(-pos2.x+pos2.y-pos2.z)/TreeRadius;
	shift = saturate(shift);

	Out.color.r = shift;
	Out.color.g = shift;
	Out.color.b = shift;
	Out.color.a = 1.0f;

	Out.shadowMapTexcoord = mul(pos, WorldViewProjectionMatrix);

	return Out; 
} 

float4 PS_SHADOW_TREE(VS_SHADOW_TREE_OUT In) : COLOR
{ 
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float4 shadow = tex2D(ShadowMapSampler, texcoord).r;
//	shadow = max(Ambient, shadow*shadow);
	shadow.a = 1.0f;
	
	return In.color*shadow*tex2D(DiffuseSamper, In.texcoord);
}

//-----------------------------------------------------------------------------

struct VS_MAKE_SHADOW_IMAGE_OUT
{ 
	float4 pos : POSITION; 

	float4 shadowMapTexcoord : TEXCOORD;
}; 

VS_MAKE_SHADOW_IMAGE_OUT VS_MAKE_SHADOW_IMAGE(float4 pos : POSITION)
{ 
	VS_MAKE_SHADOW_IMAGE_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);

	Out.shadowMapTexcoord = mul(pos, LightWorldViewProjectionMatrix);

	return Out; 
} 

float4 PS_MAKE_SHADOW_IMAGE(VS_MAKE_SHADOW_IMAGE_OUT In) : COLOR
{ 
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float4 color = 1.0f;
	if (In.shadowMapTexcoord.z/In.shadowMapTexcoord.w > tex2D(ShadowMapSampler, texcoord).x+Z_SHIFT) color = Ambient; 

	color.a = 1.0f;

	return color;
}

//-----------------------------------------------------------------------------
// enable texture alpha such as tree

struct VS_MAKE_SHADOW_IMAGE_TEX_OUT
{ 
	float4 pos : POSITION; 
	float2 texcoord : TEXCOORD0;

	float4 shadowMapTexcoord : TEXCOORD1;
}; 

VS_MAKE_SHADOW_IMAGE_TEX_OUT VS_MAKE_SHADOW_IMAGE_TEX(float4 pos : POSITION, float2 texcoord : TEXCOORD)
{ 
	VS_MAKE_SHADOW_IMAGE_TEX_OUT Out; 

	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord; 

	Out.shadowMapTexcoord = mul(pos, LightWorldViewProjectionMatrix);

	return Out; 
} 

float4 PS_MAKE_SHADOW_IMAGE_TEX(VS_MAKE_SHADOW_IMAGE_TEX_OUT In) : COLOR
{ 
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float4 color = 1.0f;
	if (In.shadowMapTexcoord.z/In.shadowMapTexcoord.w > tex2D(ShadowMapSampler, texcoord).x+Z_SHIFT) color = Ambient; 

	color.a = tex2D(DiffuseSamper, In.texcoord).w;	

	return color;
}

//-----------------------------------------------------------------------------

struct VS_SIMPLE_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
};

VS_SIMPLE_OUT VS_SIMPLE(float4 pos : POSITION, float2 texcoord : TEXCOORD0)
{
	VS_SIMPLE_OUT Out;
	
	Out.pos = pos;
	Out.texcoord = texcoord;
	
	return Out;
}

//-----------------------------------------------------------------------------

float4 PS_BLUR_U(VS_SIMPLE_OUT In) : COLOR0
{
	float2 texel0 = In.texcoord+float2(-BlurU[0], 0.0f);
	float2 texel1 = In.texcoord+float2(-BlurU[1], 0.0f);
	float2 texel2 = In.texcoord+float2(-BlurU[2], 0.0f);
	float2 texel3 = In.texcoord+float2(-BlurU[3], 0.0f);
	float2 texel4 = In.texcoord+float2(-BlurU[4], 0.0f);
		
	float2 texel5 = In.texcoord+float2(BlurU[0], 0.0f);
	float2 texel6 = In.texcoord+float2(BlurU[1], 0.0f);
	float2 texel7 = In.texcoord+float2(BlurU[2], 0.0f);
	float2 texel8 = In.texcoord+float2(BlurU[3], 0.0f);
	float2 texel9 = In.texcoord+float2(BlurU[4], 0.0f);

	float4 p0 = tex2D(ShadowMapSampler, In.texcoord)*0.20f;
		
	float4 p1 = tex2D(ShadowMapSampler, texel0)*0.12f;
	float4 p2 = tex2D(ShadowMapSampler, texel1)*0.10f;
	float4 p3 = tex2D(ShadowMapSampler, texel2)*0.08f;
	float4 p4 = tex2D(ShadowMapSampler, texel3)*0.06f;		
	float4 p5 = tex2D(ShadowMapSampler, texel4)*0.04f;
	
	float4 p6 = tex2D(ShadowMapSampler, texel5)*0.12f;
	float4 p7 = tex2D(ShadowMapSampler, texel6)*0.10f;
	float4 p8 = tex2D(ShadowMapSampler, texel7)*0.08f;
	float4 p9 = tex2D(ShadowMapSampler, texel8)*0.06f;
	float4 p10 = tex2D(ShadowMapSampler, texel9)*0.04f;

	return p0+p1+p2+p3+p4+p5+p6+p7+p8+p9+p10;
}

float4 PS_BLUR_V(VS_SIMPLE_OUT In) : COLOR0
{
	float2 texel0 = In.texcoord+float2(0.0f, -BlurV[0]);
	float2 texel1 = In.texcoord+float2(0.0f, -BlurV[1]);
	float2 texel2 = In.texcoord+float2(0.0f, -BlurV[2]);
	float2 texel3 = In.texcoord+float2(0.0f, -BlurV[3]);
	float2 texel4 = In.texcoord+float2(0.0f, -BlurV[4]);
		
	float2 texel5 = In.texcoord+float2(0.0f, BlurV[0]);
	float2 texel6 = In.texcoord+float2(0.0f, BlurV[1]);
	float2 texel7 = In.texcoord+float2(0.0f, BlurV[2]);
	float2 texel8 = In.texcoord+float2(0.0f, BlurV[3]);
	float2 texel9 = In.texcoord+float2(0.0f, BlurV[4]);

	float4 p0 = tex2D(ShadowMapSampler, In.texcoord)*0.20f;
		
	float4 p1 = tex2D(ShadowMapSampler, texel0)*0.12f;
	float4 p2 = tex2D(ShadowMapSampler, texel1)*0.10f;
	float4 p3 = tex2D(ShadowMapSampler, texel2)*0.08f;
	float4 p4 = tex2D(ShadowMapSampler, texel3)*0.06f;		
	float4 p5 = tex2D(ShadowMapSampler, texel4)*0.04f;
	
	float4 p6 = tex2D(ShadowMapSampler, texel5)*0.12f;
	float4 p7 = tex2D(ShadowMapSampler, texel6)*0.10f;
	float4 p8 = tex2D(ShadowMapSampler, texel7)*0.08f;
	float4 p9 = tex2D(ShadowMapSampler, texel8)*0.06f;
	float4 p10 = tex2D(ShadowMapSampler, texel9)*0.04f;

	return p0+p1+p2+p3+p4+p5+p6+p7+p8+p9+p10;
}

//-----------------------------------------------------------------------------

float4 PS_MAKE_WAVE(VS_SIMPLE_OUT In) : COLOR0
{
	// r-height g-speed
	float4 wave = tex2D(tex0, In.texcoord);
	
	float height1 = tex2D(tex0, In.texcoord+float2(PixelSize, 0.0f)).r;
	float height2 = tex2D(tex0, In.texcoord+float2(0.0f, PixelSize)).r;
	float height3 = tex2D(tex0, In.texcoord+float2(-PixelSize, 0.0f)).r;
	float height4 = tex2D(tex0, In.texcoord+float2(0.0f, -PixelSize)).r;

	float speed = wave.g+((height1+height2+height3+height4)*0.25f-wave.r)*SpringPower;
	float height = wave.r+speed;

	// new wave
	if (distance(In.texcoord, AddWavePos) < 0.005f) speed += AddWaveSpeed;

	return float4(height, speed, 1.0f, 1.0f);
}

float4 PS_MAKE_WAVE_BUMP(VS_SIMPLE_OUT In) : COLOR0
{
	float4 Out;

	float height1 = tex2D(tex0, In.texcoord+float2(PixelSize, 0.0f)).r;
	float height2 = tex2D(tex0, In.texcoord+float2(0.0f, PixelSize)).r;
	float height3 = tex2D(tex0, In.texcoord+float2(-PixelSize, 0.0f)).r;
	float height4 = tex2D(tex0, In.texcoord+float2(0.0f, -PixelSize)).r;
	
	// calculate x height difference
	// change -1.0f - 1.0f to 0.0f - 1.0f
	float tu = (height3-height1)*0.5f+0.5f;

	// calculate y height difference
	float tv = (height4-height2)*0.5f+0.5f;
	
	Out = float4(tu, tv, 1.0f, 1.0f);

	return Out;
}

//-----------------------------------------------------------------------------

struct VS_WAVE_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
	float3 localLightVector : TEXCOORD1;
	float3 halfVector : TEXCOORD2;

	float3 WorldNormal : TEXCOORD4;
	float3 WorldCameraVector : TEXCOORD5;
};

VS_WAVE_OUT VS_WAVE(float4 pos : POSITION, float3 tangent : TANGENT, float3 binormal : BINORMAL, float3 normal : NORMAL, float2 texcoord : TEXCOORD0)
{
	VS_WAVE_OUT Out;
	
	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord;

	Out.localLightVector.x = dot(LocalLightVector, tangent);
	Out.localLightVector.y = dot(LocalLightVector, binormal);
	Out.localLightVector.z = dot(LocalLightVector, normal);
	
	float3 halfVector = normalize(LocalLightVector+normalize(LocalCameraPos-pos.xyz));
		
	Out.halfVector.x = dot(halfVector, tangent);
	Out.halfVector.y = dot(halfVector, binormal);
	Out.halfVector.z = dot(halfVector, normal);
	
	Out.WorldNormal = mul(normal, (float3x3)WorldMatrix);
	Out.WorldCameraVector = (float3)mul(pos, WorldMatrix)-WorldCameraPos;

	return Out;
}

float4 PS_WAVE(VS_WAVE_OUT In) : COLOR
{   
    float3 normal = normalize(tex2D(NormalSamper, In.texcoord).rgb*2.0f-1.0f);
    
	float4 color = Color*max(Ambient, dot(normal, In.localLightVector))
		+Specular*pow(max(0.0f, dot(normal, normalize(In.halfVector))), SpecularPow);				// phong (pow = 80)

	color.a = 1.0f;	

	return color*tex2D(DiffuseSamper, In.texcoord)
		+texCUBE(CubeTexSampler, reflect(In.WorldCameraVector, normal))*Reflection;					// environmental color
}

//-----------------------------------------------------------------------------

struct VS_SHADOW_WAVE_OUT
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
	float3 localLightVector : TEXCOORD1;
	float3 halfVector : TEXCOORD2;

	float3 WorldNormal : TEXCOORD4;
	float3 WorldCameraVector : TEXCOORD5;

	float4 shadowMapTexcoord : TEXCOORD6;
};

VS_SHADOW_WAVE_OUT VS_SHADOW_WAVE(float4 pos : POSITION, float3 tangent : TANGENT, float3 binormal : BINORMAL, float3 normal : NORMAL, float2 texcoord : TEXCOORD0)
{
	VS_SHADOW_WAVE_OUT Out;
	
	Out.pos = mul(pos, WorldViewProjectionMatrix);
	Out.texcoord = texcoord;

	Out.localLightVector.x = dot(LocalLightVector, tangent);
	Out.localLightVector.y = dot(LocalLightVector, binormal);
	Out.localLightVector.z = dot(LocalLightVector, normal);
	
	float3 halfVector = normalize(LocalLightVector+normalize(LocalCameraPos-pos.xyz));
		
	Out.halfVector.x = dot(halfVector, tangent);
	Out.halfVector.y = dot(halfVector, binormal);
	Out.halfVector.z = dot(halfVector, normal);
	
	Out.WorldNormal = mul(normal, (float3x3)WorldMatrix);
	Out.WorldCameraVector = (float3)mul(pos, WorldMatrix)-WorldCameraPos;

	Out.shadowMapTexcoord = Out.pos;

	return Out;
}

float4 PS_SHADOW_WAVE(VS_SHADOW_WAVE_OUT In) : COLOR
{   
	float2 texcoord;
	texcoord.x = (1.0f+In.shadowMapTexcoord.x/In.shadowMapTexcoord.w)*0.5f;
	texcoord.y = (1.0f-In.shadowMapTexcoord.y/In.shadowMapTexcoord.w)*0.5f;
	
	float shadow = tex2D(ShadowMapSampler, texcoord).r;

    float3 normal = normalize(tex2D(NormalSamper, In.texcoord).rgb*2.0f-1.0f);
    
	float4 color = Color*max(Ambient, shadow*dot(normal, In.localLightVector))
		+Specular*shadow*pow(max(0.0f, dot(normal, normalize(In.halfVector))), SpecularPow);				// phong (pow = 80)

	color.a = 1.0f;	

	return color*tex2D(DiffuseSamper, In.texcoord)
		+texCUBE(CubeTexSampler, reflect(In.WorldCameraVector, normal))*Reflection;					// environmental color
}

//-----------------------------------------------------------------------------
technique shader
{
	pass P0
	{
		VertexShader = compile vs_2_0 VS();
		PixelShader = compile ps_2_0 PS();
	}

	pass P1
	{
		VertexShader = compile vs_2_0 VS_ENV();
		PixelShader = compile ps_2_0 PS_ENV();
	}

	pass P2
	{
		VertexShader = compile vs_2_0 VS_BUMP();
		PixelShader = compile ps_2_0 PS_BUMP();
	}

	pass P3
	{
		VertexShader = compile vs_2_0 VS_MAKE_SHADOW();
		PixelShader = compile ps_2_0 PS_MAKE_SHADOW();
	}

	pass P4
	{
		VertexShader = compile vs_2_0 VS_MAKE_SHADOW_TEX();
		PixelShader = compile ps_2_0 PS_MAKE_SHADOW_TEX();
	}

	pass P5
	{
		VertexShader = compile vs_2_0 VS_SHADOW();
		PixelShader = compile ps_2_0 PS_SHADOW();
	}

	pass P6
	{
		VertexShader = compile vs_2_0 VS_SHADOW_ENV();
		PixelShader = compile ps_2_0 PS_SHADOW_ENV();
	}

	pass P7
	{
		VertexShader = compile vs_2_0 VS_SHADOW_BUMP();
		PixelShader = compile ps_2_0 PS_SHADOW_BUMP();
	}

	pass P8
	{
		VertexShader = compile vs_2_0 VS_TREE();
		PixelShader = compile ps_2_0 PS_TREE();
	}

	pass P9
	{
		VertexShader = compile vs_2_0 VS_SHADOW_TREE();
		PixelShader = compile ps_2_0 PS_SHADOW_TREE();
	}

	pass P10
	{
		VertexShader = compile vs_2_0 VS_MAKE_SHADOW_IMAGE();
		PixelShader = compile ps_2_0 PS_MAKE_SHADOW_IMAGE();
	}

	pass P11
	{
		VertexShader = compile vs_2_0 VS_MAKE_SHADOW_IMAGE_TEX();
		PixelShader = compile ps_2_0 PS_MAKE_SHADOW_IMAGE_TEX();
	}

	pass P12
	{
		VertexShader = compile vs_2_0 VS_SIMPLE();
		PixelShader = compile ps_2_0 PS_BLUR_U();
	}

	pass P13
	{
		VertexShader = compile vs_2_0 VS_SIMPLE();
		PixelShader = compile ps_2_0 PS_BLUR_V();
	}

	pass P14
	{
		VertexShader = compile vs_2_0 VS_SIMPLE();
		PixelShader = compile ps_2_0 PS_MAKE_WAVE();
	}

	pass P15
	{
		VertexShader = compile vs_2_0 VS_SIMPLE();
		PixelShader = compile ps_2_0 PS_MAKE_WAVE_BUMP();
	}

	pass P16
	{
		VertexShader = compile vs_2_0 VS_WAVE();
		PixelShader = compile ps_2_0 PS_WAVE();
	}

	pass P17
	{
		VertexShader = compile vs_2_0 VS_SHADOW_WAVE();
		PixelShader = compile ps_2_0 PS_SHADOW_WAVE();
	}
}

