#version 410 core

uniform sampler2D velocityField;
uniform float time;
uniform float timeStep;
uniform float deltaX;
uniform vec4 shapeInfo[8];   // cx, cy, radius, scaler
uniform vec4 shapeParams[8]; // vx, vy, angular velocity, scaler
uniform float envelope;// = 0.17;
uniform float noiseLengthScale;// = 0.1;
uniform float noiseGain;// = 0.1;

layout (location = 0) in vec4 POSITION;


vec2 bilinear(in vec2 coord)
{
	vec2 invSize = vec2(1.0/256.0, 1.0/256.0);
	vec2 uv = floor(abs(coord)*256.0);
	vec2 k = normalize(abs(coord)*256.0 - uv);
	uv *= (1.0/256.0);

	vec2 m00 = textureLod(velocityField, uv, 0.0).xy;
	vec2 m10 = textureLod(velocityField, uv + vec2(invSize.x, 0.0), 0.0).xy;
	vec2 m01 = textureLod(velocityField, uv + vec2(0.0, invSize.y), 0.0).xy;
	vec2 m11 = textureLod(velocityField, uv + invSize, 0.0).xy;
	vec2 a = mix(m00, m10, k.x);
	vec2 b = mix(m01, m11, k.x);
	return mix(a, b, k.y);
}


void main()
{
	vec2 pos = POSITION.xy;

	vec2 randVel = (bilinear(pos*0.5) + bilinear(POSITION.zw*0.5)) * 0.5;
	vec2 worldVel = mix(vec2(0.0, 1.0), bilinear(pos*0.125), 0.4) * 0.01;
	{
		float gridSize = 2.0;
		float gridSizeHalf = gridSize/2.0;
		vec2 signs = sign(POSITION.xy);
		vec2 grid = floor(abs(POSITION.xy)*gridSize) * signs;
		vec2 diff = POSITION.xy - (grid * signs);
		float d = min(length(diff), gridSizeHalf) / gridSizeHalf;
		worldVel += diff*d*0.00005;
	}

	vec2 vel = mix(POSITION.zw, -randVel, 0.02) + worldVel;

	for (int i=0; i < 8; i++)
	{
		vec2 diff = pos - shapeInfo[i].xy;
		float d = clamp(length(diff) / (shapeInfo[i].z), 0.0, 1.0);
		vel += diff*(1.0 - d) * shapeInfo[i].w;
	}
	pos += vel*timeStep;
	vec2 diff = pos - POSITION.xy;
	float d2 = dot(diff, diff);
	if ( d2 > 0.0 ) d2 = sqrt(d2);
	float d = smoothstep(0.0, 0.2, d2);

	pos.x = mod(pos.x + 6.0, 12.0) - 6.0;
	pos.y = mod(pos.y + 4.0, 8.0) - 4.0;

	gl_Position = vec4(pos, vel);
}
