kernelp4nic
4/28/2014 - 5:44 PM

The Amplituhedron TM® (http://glsl.heroku.com/e#16354.0)

The Amplituhedron TM® (http://glsl.heroku.com/e#16354.0)

//The Amplituhedron TM®
//By nikoclass@gmail.com

#ifdef GL_ES
precision highp float;
#endif


// Uniform es constante mientras corre el shader
uniform float time;
uniform vec2 mouse; // vec2 es un tipo de dato, en este caso un vector de 2 dimensiones (coordenadas X:Y)
uniform vec2 resolution;

const float PI = 3.1415926535897932384626; // No cambian NUNCA

const float LINE_WIDTH = 0.005; // Grosor de las lineas del Amplituhedron TM®
const float DIST = 3.0; // Distancia de la camara virtual

// Globales dentro de este file
vec3 z;
vec3 y = vec3(0.0, cos(time) * 0.4, 0.0);
mat3 rot;

float line(vec3 a, vec3 b, vec2 pos) {
	// Triquiñuela para la rotación
	// (aplica traslacion y rotacion de vectores)
	a = (a - z) * rot + z + y;
	b = (b - z) * rot + z + y;
	
	vec2 a2 = vec2(a.x, a.y) / a.z;
	vec2 b2 = vec2(b.x, b.y) / b.z;
	
	// largo del segmento a2-b2
	float l = distance(a2, b2);
	
	// vector director normalizado
	vec2 r2 = (a2 - b2)/l;
	
	// pixel llevado al origen de la recta
	vec2 p = pos - b2;
	
	// producto interno entre los vectores r2 y p (producto escalar)
	float t = dot(r2, p);
	
	// la proyección del pixel a donde corta la recta
	vec2 proyect = r2 * t;
	
	// la distancia de proyect
	float dist = distance(proyect, p);
	
	// calculo del ancho
	if (t >= 0.0 && t <= l && dist < LINE_WIDTH) {
		// Degradé del color, sino sería la linea
		// completa de color solido
		float d = 1.0 - dist / LINE_WIDTH;
		return d;
	}
	return 0.0;
}

// Calcula matriz de rotación en
// base a un angulo
mat3 rotY(float ang) {
	float c = cos(ang);
	float s = sin(ang);
	return mat3(c, 0, s,
		    0, 1, 0,
		   -s, 0, c);
}

// triquiñuela para darle color a
// cada arista
float f(int i){
	return floor(mod(float(i), 4.0) / 3.0);
}

void main( void ) {
	// posición del pixel que se está dibujando ahora
	vec2 pos = gl_FragCoord.xy / resolution.xy - 0.5;
	pos.x *= (resolution.x / resolution.y);

	// coordenadas y del mouse que llegan a un maximo
	float my = max(mouse.y, 0.3) * 1.5;
	
	// radio chico de la esfera
	float RADIO_1 = 0.5 * my * my;
	
	// radio grande
	float RADIO_2 = 1.0 * sqrt(my);
		
	// Colores
	vec3 color = vec3(0.0, 0.0, 0.0);
	vec3 c1 = vec3(1.0, 0.0, 0.0);
	vec3 c2 = vec3(0.0, 1.0, 0.0);
	vec3 c3 = vec3(0.0, 0.0, 1.0);
	vec3 c4 = vec3(1.0, 1.0, 0.0);
	
	// Vector que apunta desde la vista hacia el objeto
	z = vec3(0, 0, DIST);
	
	// 2 Octogonos * 3
	for (int i = 0; i < 8 * 3; i++) {
		if (length(color) >= 1.0) {
			break;
		}
		rot = rotY(-mouse.x * 8.0 - 4.0 + float(i / 8) * PI / 3.0);
		float ang = float(i) / 4.0 * PI;
		float nextAng = float(i + 1) / 4.0 * PI;
		float b = mod(float(i), 2.0);
		float r = b * RADIO_1 + (1.0 - b) * RADIO_2;
		float r2 = b * RADIO_2 + (1.0 - b) * RADIO_1;
		
		float c = line (vec3(cos(ang) * r, sin(ang) * r, DIST), vec3(cos(nextAng) * r2, sin(nextAng) * r2, DIST), pos);
		color += c*(f(i)*c1 + f(i + 1)*c2 + f(i + 2)*c3 + f(i + 3)*c4);
		c = line (vec3(cos(ang) * r2, sin(ang) * r2, DIST), vec3(cos(nextAng) * r, sin(nextAng) * r, DIST), pos);
		color += c*(f(i + 2)*c1 + f(i + 3)*c2 + f(i + 4)*c3 + f(i + 5)*c4);
	}
	
	// Hexagono del medio
	for (int i = 0; i < 6; i++) {
		if (length(color) >= 1.0) {
			break;
		}
		rot = rotY(-mouse.x * 8.0 - 4.0);
		float ang = float(i) / 3.0 * PI;
		float nextAng = float(i + 1) / 3.0 * PI;
		float b = mod(float(i), 2.0);
		float r = b * RADIO_1 + (1.0 - b) * RADIO_2;
		float r2 = b * RADIO_2 + (1.0 - b) * RADIO_1;
		
		float c = line (vec3(cos(ang) * r, 0.0, sin(ang) * r + DIST), vec3(cos(nextAng) * r2, 0.0 , sin(nextAng) * r2 + DIST), pos);
		color += c*(f(i)*c1 + f(i + 1)*c2 + f(i + 2)*c3 + f(i + 3)*c4);
		c = line (vec3(cos(ang) * r2, 0.0 , sin(ang) * r2 + DIST), vec3(cos(nextAng) * r, 0.0, sin(nextAng) * r +  DIST), pos);
		color += c*(f(i + 1)*c1 + f(i + 2)*c2 + f(i + 3)*c3 + f(i + 4)*c4);
	}
	
	// background
	if (length(color) == 0.0) {
		gl_FragColor = vec4((vec3(cos(-time + pos.x*10.0), cos(-time *1.3 + pos.y*10.0), cos(time* pos.x*pos.y*2.0)*2.0) * dot(pos, pos) * 0.5), 1.0 );
	}
	else {
		gl_FragColor = vec4( color, 1.0 );
	}

}