%%VSHADER-HEAD%%

uniform vec2 a0;
uniform vec2 a1;
uniform vec2 a2;
uniform vec2 a3;

uniform vec2 pos;

uniform float timeshift;
uniform float wq;
uniform float hq;
uniform float width_exponent;
uniform int span;

float pi = 2.0 * asin(1.0);

// sign() is available since GLSL 1.3, but we are using GLSL 1.1.
// mangle the name to avoid a clash in case the implementation provides it anyway.
#define sign _ts_sign

float sign(float x) {
    return float(x > 0.0) - float(x < 0.0);
}

vec2 dir(float a) {
	return vec2(cos(a), sin(a));
}

float angle(vec2 v) {
	return atan(v.y, v.x);
}

vec2 cmul(vec2 c1, vec2 c2) {
	// complex multiplication
	// x = real, y = imaginary
	return vec2(c1.x*c2.x - c1.y*c2.y, c1.x*c2.y + c1.y*c2.x);
}

vec2 posrule(float t) {
%%VSHADER-FOOT%%
}

void main(void) {
	vec2 v = gl_Vertex.xy;

	float t1 = gl_InstanceID-span/2;
	float tail = span/1.9;

	float s = -0.75/pow(tail,2)*(t1-tail)*(t1+tail);

	vec2 pos = posrule(gl_InstanceID*0.5+timeshift);
	vec2 d = pos - posrule(gl_InstanceID*0.5+timeshift-0.1);

	float a = -angle(d);
	mat2 m = mat2(cos(a), -sin(a), sin(a), cos(a));

	v.x *= wq*1.5*length(d);
	v.y *= hq*pow(s, width_exponent);

	gl_Position     = gl_ModelViewProjectionMatrix*vec4(m*v+pos, 0.0, 1.0);
	gl_TexCoord[0]  = gl_MultiTexCoord0;
}

%%FSHADER-HEAD%%

#version 120

uniform sampler2D tex;
uniform vec4 clr;

void main(void) {
	gl_FragColor = texture2D(tex, vec2(gl_TexCoord[0].xy))*clr;
}

%%linear%%
return pos + a0*t;
%%accelerated%%
return pos + a0*t + 0.5*a1*t*t;
%%maxwell%%
vec2 p = vec2(t, a2.x*t*0.02*sin(0.1*t+a2.y));
return pos + vec2(a0.x*p.x - a0.y*p.y, a0.x*p.y + a0.y*p.x);
%%sine%%
vec2 line_vel = a0;
vec2 line_dir = line_vel / length(line_vel);
vec2 line_normal = vec2(line_dir.y, -line_dir.x);
float sine_amp = a1.x;
float sine_freq = a2.x;
float sine_phase = a3.x;
vec2 sine_ofs = line_normal * sine_amp * sin(sine_freq * t + sine_phase);
return pos + t * line_vel + sine_ofs;
%%weird_sine%%
float s = (a2.x * t + a3.x);
return pos + dir(angle(a0) + a1.x * sin(s) / s) * t * length(a0);
%%sine_expanding%%
float s = (a2.x * t + a3.x);
return pos + dir(angle(a0) + a1.x * sin(s)) * t * length(a0);
%%turning%%
vec2 v0 = a0;
vec2 v1 = a1;
float begin = a2.x;
float end = a2.y;
float a = clamp((t - begin) / (end - begin), 0.0, 1.0);
a = 1.0 - (0.5 + 0.5 * cos(a * pi));
a = 1.0 - pow(1.0 - a, 2);
return pos + mix(v0, v1, a) * t;
%%circle%%
// XXX: should turn speed be in rad/sec or rad/frame? currently rad/sec.
float turn_speed = a0.x / 60;
float time_ofs = a0.y;
float radius = a1.x;
return pos + radius * dir((t + time_ofs) * turn_speed);
%%iku_lightning%%
float diff = a2.x;
return vec2(
	a0.x + a1.x * (20.0 + 4.0 * diff) * sin(t * 0.025 * diff + a0.x),
	pos.y + sign((a0 - pos).y) * 0.06 * t * t
);
%%iku_cathode%%
return pos + cmul(t * a0, dir(a1.y * t));
%%elly_toe_fermion%%
return pos + a0*t;
%%elly_toe_photon%%
return pos+cmul(a0,vec2(t,a2.x*sin(t/a2.x)));
%%elly_toe_gluon%%
return pos+cmul(a0,vec2(t+a2.x*(0.6*(cos(3.*t/a2.x)-1.)),a2.x*sin(3.*t/a2.x)));
%%elly_toe_higgs%%
return pos+a0*(t+floor(t/a2.x)*a2.x);
