#version 330 core

uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform float time;
uniform vec4 superShapeParams; // m, n1, n2, n3
uniform vec4 morphParams; // radius, morph, a, b
uniform int instanceBufferOffset;
uniform samplerBuffer instanceData;

layout (location = 0) in vec3 POSITION;
layout (location = 1) in vec3 NORMAL;
layout (location = 4) in vec2 TEXCOORD;

out vec2 pos_zw;
out vec3 normal;
out vec3 ec_pos;
out vec3 uv_shade;

#define PI 3.1415926
#define TWO_PI 6.2831853

vec3 fromCylinder(float radius, float theta, float height)
{
	vec3 pos;
	pos.x = radius * cos(theta);
	pos.y = radius * sin(theta);
	pos.z = height;
	return pos;
}


vec2 superShape(in vec2 coord)
{
	float phi = atan(coord.y, coord.x);

	float t1 = cos(superShapeParams.x * phi / 4.0) / morphParams.z;
	t1 = pow(abs(t1), superShapeParams.z);
	
	float t2 = sin(superShapeParams.x * phi / 4.0) / morphParams.w;
	t2 = pow(abs(t2), superShapeParams.w);
	
	float r = 1.0 / pow(t1 + t2, 1.0 / superShapeParams.y);

	return vec2(cos(phi), sin(phi)) * r;
}

void main()
{
	vec4 instPos = texelFetch(instanceData, gl_InstanceID + instanceBufferOffset);
	vec3 cylPos = fromCylinder(2.0 + (instPos.w - 0.75) * 0.5, time*0.5 + PI*instPos.x/8.0, instPos.z);

	//instPos.x += (mod(8.0 + instPos.x + time*0.5, 16.0) - 8.0)*0.8*0.000001;
	instPos.x += sin(instPos.z + time*0.5) * 0.1;
	instPos.z += sin(instPos.x + time*0.5) * 0.1;
	instPos.y += sin(instPos.x + instPos.z + time*0.5) * 0.75;

	float radius = length(instPos.xz);
	vec2 ssPos = superShape(instPos.xz) * mix(radius, 1.0, morphParams.x);

	instPos.xyz = mix(instPos.xyz, cylPos, morphParams.y);
	instPos.xz = mix(instPos.xz, ssPos, morphParams.y*0.0001);
	instPos.y += (instPos.w - 0.75) * 2.6 - 1.3;
	float scale = sin(length(instPos.xz)*2.0);

	vec3 cubePos = POSITION*instPos.w*(1.0/32.0);
	//cubePos.y *= abs(instPos.y*8.0);
	vec3 pos = cubePos + instPos.xyz;
	vec3 dir = normalize(vec3(pos.x, 2.0, pos.z)*2.0);
	pos += dir * scale * 0.015;

	uv_shade.xy = TEXCOORD;
	uv_shade.z = instPos.w * instPos.w * instPos.w;
	normal = NormalMatrix * NORMAL;

	ec_pos = vec3(ModelViewMatrix * vec4(pos, 1.0));

	vec4 proj_pos = ModelViewProjectionMatrix * vec4(pos, 1.0);
	pos_zw = proj_pos.zw;
	gl_Position = proj_pos;
}
