//
// ASGenieKernel.cikernel
//
// (c) Aderstedt Software AB 2008.
// Erik Aderstedt 2008-09-05.
// 

kernel vec4 ASGenieKernel(sampler src, float t, float D, float ytarget, float scale)
{
	// Given a point (destCoord) we are tasked to find its colour.
	// We do it by finding a source point (takeFrom) and take its
	// colour. If no source point can be found, we return the
	// colour (0.0,0.0,0.0,0.0).
	
	// Given a point in the original image, where do we end up?
	// A transformation from takeFrom -> destCoord.
	// At t = 0: destCoord = takeFrom.
	// At t = 1: destCoord = (takeFrom - ytarget)*D/ymax + ytarget
	// At t = t: destCoord = takeFrom*(1-t) + t*((takeFrom - ytarget)*D/ymax + ytarget)
	//					   = takeFrom*(1-t+t*D/ymax) + t*ytarget-t*ytarget*D/ymax
	//					   = takeFrom*(1-t*(1-D/ymax)) + t*ytarget*(1-D/ymax)
	// ->  takeFrom.y = (destCoord.y - t*ytarget*(1-D/ymax))/(1-t*(1-D/ymax))
	// destCoord.y = ymax, D = 0.04*ymax, t = 0.5 -> (ymax - 0.5*ytarget*0.96)/(1-0.5*0.96). ymax = 1, ytarget = 0.5 -> 0.75/0.5 -> 1.5.
	// If takeFrom.y is out of bounds, we set the alpha to 0 and return immediately.
	//
	// Use an envelope function. From 1 to 0. (1-tan((x/xmax * pi/2) - pi/4))/2.
	// Multiply the t value with that in the expression above.
	// For t > 1 we also transform the x coordinate using a simple linear transformation.
	// At t > 1 the y shape is fixed, so we set t = 1 before applying the envelope (but after
	// applying the transformation).
	
	vec2 takeFrom; // In destination coordinates.
	vec2 original = samplerCoord(src);
	vec2 size;
	float g, t2, a;
	vec4 c;
	
	size = samplerSize(src);
    original = vec2(original.x / scale, original.y / scale);
	t2 = compare(t-1.0,t,1.0);
	takeFrom.x = original.x + compare(t-1.0,0.0,1.0)*size.x*(t-1.0);
	
	a = compare(takeFrom.x, 0.0, 1.0);
	a = compare(a-0.5,0.0,compare(takeFrom.x-size.x, 1.0, 0.0));
	
	// Apply an envelope. This is where non-linearity is introduced. 
	t2 = t2 * (1.0 - tan_(1.57*original.x/size.x - 0.78539))*0.5;
	
	g = 1.0 - D / size.y;
	takeFrom.y = (original.y - t2*ytarget*g)/(1.0-t2*g);
	a = compare(a-0.5,0.0,compare(takeFrom.y, 0.0, 1.0));
	a = compare(a-0.5,0.0,compare(takeFrom.y-size.y, 1.0, 0.0));
	
	takeFrom.x = compare(takeFrom.x, 0.0, takeFrom.x);
	takeFrom.x = compare(takeFrom.x-size.x, takeFrom.x, 0.0);
	takeFrom.y = compare(takeFrom.y, 0.0, takeFrom.y);
	takeFrom.y = compare(takeFrom.y-size.y, takeFrom.y, 0.0);
	
    takeFrom = vec2(takeFrom.x*scale, takeFrom.y*scale);
	c = sample(src, takeFrom);
	c.w = a;
	
	return c;
}