#version 330 core

uniform float time;
uniform vec2 resolution;
uniform vec2 wPos;
uniform vec2 wRad;

in vec2 mypos;
in vec4 aPos;
out vec4 fragColor;

float pi = atan(1.0) * 4.0;
float tau = atan(1.0) * 8.0;

#define DALI_MODE

//2D Distance Field Stuff

//Transformations
vec2 Rotate(vec2 uv,float angle);

//Shapes
float Circle(vec2 uv,float r);
float Rect(vec2 uv,vec2 size,float r);
float Line(vec2 uv,vec2 start,vec2 end,float r);

//Shape Operations
float Merge(float a,float b); //Combine two objects
float Carve(float a,float b); //Carve object b from object a
float Intersect(float a,float b); //Intersect two objects
float Outline(float a,float r); //Creates an outline of an object

//Shape Coloring
vec3 Blend(vec3 backColor, vec3 shapeColor, float shape);

float SecStep(float x); //Delayed step with recoil



// halfspace discard uniforms: ////////////////////////////////////

uniform int iside=0; // 0=>noDiscard

uniform vec3 eyePos;

uniform vec3  port1;
uniform vec3  port2;

// halfspace discard uniforms end /////////////////////////////////





void main( void ) 
{
	//vec2 uv = ( mypos / resolution.xy );
	//vec2 res = resolution / resolution.y;
	//uv -= res / 2.0;

	float rtime = -time;
	vec2 uv = 0.5*(mypos-wPos)/wRad;
	
	#ifdef DALI_MODE
	uv.x += cos(uv.y*16.0+rtime)*0.05;
	uv.y += cos(uv.x*4.0+rtime)*0.05;
	uv = Rotate(uv,sin(rtime+length(uv)*4.0)*0.3);
	#endif
	
	vec3 color = vec3(0.02);
	
	//Clock hand angles
	float secAng = -(SecStep(rtime) / 60.0) * tau;
	float minAng = -(rtime / 3600.0) * tau;
	float hourAng = -(rtime / 86400.0) * tau;
	
	//Clock case
	float clockFace = Circle(uv, 0.45);
	float clockTrim = Outline(clockFace, 0.01);
	
	vec2 secDomain = Rotate(uv, secAng); //Rotated uv coords for the second hand (used for placing the counter balence)
	
	//Seconds hand
	float clockSec = Line(secDomain, vec2(0.0, -0.05), vec2(0.0, 0.35), 0.001);
	clockSec = Merge(clockSec, Circle(uv, 0.01));
	clockSec = Merge(clockSec, Rect(secDomain.yx - vec2(-0.08, 0.0), vec2(0.07, 0.01), 0.0));
	
	//Minutes hand
	float clockMin = Line(Rotate(uv, minAng), vec2(0.0,-0.05), vec2(0.0, 0.35), 0.005);
	
	//Hours hand
	float clockHour = Line(Rotate(uv, hourAng), vec2(0.0,-0.05), vec2(0.0,0.3), 0.005);
	clockHour = Merge(clockHour, Circle(uv, 0.018));
	
	//Tick marks
	float tickMarks = 1.0;
	
	vec2 tickDomain = uv;
	
	for(int i = 0;i < 60;i++)
	{
		tickDomain = Rotate(tickDomain, tau / 60.0);
		
		vec2 size = (mod(float(i + 1), 5.0) == 0.0) ? vec2(0.08, 0.01) : vec2(0.04, 0.002); //every 5th mark is larger
		
		tickMarks = Merge(tickMarks, Rect(tickDomain - vec2(0.38, 0.0), size, 0.0));
	}
	
	//Object Coloring
	vec3 faceColor = mix(vec3(0.25), vec3(1.0), uv.y+0.5); //Clock face gradient
	faceColor *= smoothstep(0.00,-0.02, clockFace); //Trim shadow
	faceColor *= smoothstep(-0.45,-0.42, clockFace); //Hub shadow
	
	vec3 trimColor = mix(vec3(0.1), vec3(0.3), uv.y + 0.5); //Trim gradient
	
	vec3 secColor = mix(vec3(0.05, 0.0, 0.0), vec3(1.0, 0.0, 0.0), uv.y + 0.5); //Red seconds hand
	vec3 handColor = mix(vec3(0.05), vec3(0.2), uv.y + 0.5); //Minute and hour hands color
	
	//Blend coloring with objects
	color = Blend(color, faceColor, clockFace);
	color = Blend(color, trimColor, tickMarks);
	color = Blend(color, trimColor, clockTrim);
	
	color = Blend(color, handColor, clockHour);
	color = Blend(color, handColor, clockMin);
	color = Blend(color, secColor, clockSec);	

	fragColor = vec4(color, 1.0);





	// fastrgv:  my halfspace-discard addendum:
	vec3 cP1 =  port1 - eyePos;
	vec3 cP2 =  port2 - eyePos;
	vec3 vP0 = aPos.xyz - eyePos;
	float PRAD = 0.80; // larger, but synched with adagate.adb
	float FOV1 = atan(PRAD/length(cP1));
	float FOV2 = atan(PRAD/length(cP2));
	vec3 nP1 = normalize(cP1);
	vec3 nP2 = normalize(cP2);
	vec3 nP0 = normalize(vP0);
	float d1=dot(nP0,nP1);
	float d2=dot(nP0,nP2);
	float a1=acos(d1);
	float a2=acos(d2);
	if( iside != 0 ) {
		if( (iside==2) && (a1>FOV1) ) discard;
		if( (iside==1) && (a2>FOV2) ) discard;
	}


}



//Delayed step with recoil
float SecStep(float x)
{
	float interp = smoothstep(0.80, 1.0, mod(x, 1.0));
	return floor(x) + interp + (sin(interp * pi)) ;
}

//Transformations
vec2 Rotate(vec2 uv,float angle)
{
	return uv*mat2(cos(angle), sin(angle),-sin(angle), cos(angle));
}

//Shapes
float Circle(vec2 uv,float r)
{
	return length(uv) - r;	
}

float Rect(vec2 uv,vec2 size,float r)
{
	return length(uv - clamp(uv,-size / 2.0, size / 2.0)) - r;	
}

float Line(vec2 uv,vec2 start,vec2 end,float r)
{
	vec2 dir = normalize(end - start);
	uv -= start;
	uv *= mat2(dir, dir.yx * vec2(-1, 1));
	return 	length(uv - clamp(uv, vec2(0), vec2(length(start - end), 0))) - r;
}
//Shape Operations
float Merge(float a,float b)
{
	return min(a, b);	
}

float Carve(float a,float b)
{
	return max(a,-b);	
}

float Intersect(float a,float b)
{
	return max(a, b);	
}

float Outline(float a,float r)
{
	return abs(a) - r;	
}

//Shape Coloring
vec3 Blend(vec3 backColor, vec3 shapeColor, float shape)
{
	float edge = smoothstep(0.0, 1.1 / resolution.y, shape);
	return mix(shapeColor, backColor, edge);
}

//--
//-- Copyright (C) 2019  <fastrgv@gmail.com>
//--
//-- This program is free software: you can redistribute it and/or modify
//-- it under the terms of the GNU General Public License as published by
//-- the Free Software Foundation, either version 3 of the License, or
//-- (at your option) any later version.
//--
//-- This program is distributed in the hope that it will be useful,
//-- but WITHOUT ANY WARRANTY; without even the implied warranty of
//-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//-- GNU General Public License for more details.
//--
//-- You may read the full text of the GNU General Public License
//-- at <http://www.gnu.org/licenses/>.
//--

