sampler scene: register(s0);
sampler samplerPrec: register(s1);
uniform float4 camera_right;
uniform float4 camera_up;

uniform float coverage;
uniform float4 camera_vector;
uniform float4 wind_vector;
uniform float4 camera_direction;
uniform float time;

uniform float4 view_direction;
uniform float4 view_side_vector;
uniform float4 view_up_vector;
uniform float type;
uniform float dropSpeed;
uniform float appTime;

// Cartesian to cylindrical coordinates
float2 CylindricalCoordinates(float4 dir) {
	float R = 0.5;
	float2 res;
	//cubical root is used to counteract top/bottom circle effect
	dir *= R / pow(length(dir.xz), 0.33);
	res.y = dir.y;
	res.x = -atan2(dir.z, dir.x);
	return res;
}

// Cartesian to spherical coordinates
float2 SphericalCoordinates(float4 dir) {
	float2 res;
	res.x = atan2(length(dir.xy), dir.z);
	res.y = atan2(dir.y, dir.x);
	return res;
}

// Rotation matrices from angles
float4x4 XRotationMatrix(float alfa) {
	float4x4 M =
	float4x4(1, 0, 0, 0,
			0, cos(alfa), -sin(alfa), 0,
			0, sin(alfa), cos(alfa), 0,
			0, 0, 0, 1);			
	return M;
}
float4x4 YRotationMatrix(float alfa) {
	float4x4 M =
	float4x4(cos(alfa), 0, sin(alfa), 0,
			0, 1, 0, 0,
			-sin(alfa), 0, cos(alfa), 0,
			0, 0, 0, 1);
	return M;
}
float4x4 ZRotationMatrix(float alfa) {
	float4x4 M =
	float4x4(cos(alfa), -sin(alfa), 0, 0,
			sin(alfa), cos(alfa), 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1);			
	return M;
}

float4x4 RotationMatrix(float alfa, float beta, float teta) {
	return mul(mul(XRotationMatrix(alfa), ZRotationMatrix(teta)), YRotationMatrix(beta));
}

// Rotates V1 by V2 (if V1 would be a standard front vector V2 should be returned)
float4 RotateVectorByVector(float4 V1, float4 V2) {
	float halfpi=1.57079633;
	float2 Angles=SphericalCoordinates(V2);
	return mul(V1,RotationMatrix(Angles.x + halfpi, Angles.y, 0));
}

// Returns alpha value of a precipitation
// view_direction is the direction vector resulting from the eye direction,wind direction and possibly other factors
// intensity is the speed with which a drop falls along the cylinder's axis
float Precipitation
	(
		float4 view_direction,
		float coverage,
		float2 delta,
		float intensity
	) {
	float2 ccol=CylindricalCoordinates(view_direction);
	ccol.y -= intensity * appTime;
	ccol += delta;
	float4 raincol=tex2D(samplerPrec, ccol);
	return (raincol.g<coverage) ? (raincol.r) : 1;
}

// Custom sinusoidal function
float SqSine(float x) {
	return (sin(x) * sin(x)) / 5;
}

//main entry point
void MainFP
(
	in float2 scr_pos : TEXCOORD0,
	out float4 out_colour : COLOR	
) {
	//scr_pos is used to reconstruct the actual eye vector from the view front,side and up vectors
	float scrx=((scr_pos.x - 0.5) * 2);
	float scry=((scr_pos.y - 0.5) * 2) * 3 / 4;
	view_direction+=(view_side_vector * scrx - view_up_vector * scry);
	float4 drop_vector=float4(0, -dropSpeed, 0, 1);
	view_direction=RotateVectorByVector(view_direction, wind_vector + drop_vector);

	float4 scenecol=tex2D(scene,scr_pos);
	float intensity=length(wind_vector.xyz+camera_vector.xyz+drop_vector.xyz);
	float prec1=Precipitation(view_direction,coverage / 5,float2(SqSine(appTime) / 2,0),intensity * 0.5);
	float prec2=Precipitation(view_direction,coverage / 5,float2(SqSine(appTime * 1.2) / 1.5,0),intensity * 1.0);
	float prec3=Precipitation(view_direction,coverage / 5,float2(SqSine(appTime * 1.5) / 3.0,0),intensity * 1.5);
	out_colour=lerp(float4(0.8, 0.8, 0.8, 1),scenecol,min(min(prec1, prec2), prec3));
}

void MainVP
(
    in float4 in_pos : POSITION,
    
    uniform float4x4 worldviewproj_matrix,
    
    out float2 out_uv0 : TEXCOORD0,
    out float4 out_pos : POSITION
)
{
    // Use standard transform.
    out_pos = mul(worldviewproj_matrix, in_pos);

    // Convert to image-space
    in_pos.xy = sign(in_pos.xy);
    out_uv0 = (float2(in_pos.x, -in_pos.y) + 1.0f) * 0.5f;    
}
