#version 330 core

in vec4 polozenie;
in vec4 kolor;
in vec2 wspTekstur;
in vec3 polozenie_scena;
in vec3 normalna_scena;
in vec2 polozenie_kamera;

//parametry zrodla swiatla
uniform vec4 Ca = vec4(1,1,1,1);
uniform vec4 Cd = vec4(1,1,1,1);
uniform vec4 Cs = vec4(1,1,1,1);
uniform vec3 PolozenieZrodlaSwiatla = vec3(5,2,1);
uniform vec3 PolozenieKamery = vec3(0,0,1);

//parametry materialu
const float wa = 0.1;
const float wd = 1.0;
//const float ws = 0.3;
uniform vec4 Wa = vec4(wa,wa,wa,1);
uniform vec4 Wd = vec4(wd,wd,wd,1);
uniform vec4 Ws = vec4(0,1,0,1);
uniform float WNs = 100.0;

uniform bool OslabienieOswietlenia = false;
uniform vec3 WspolczynnikiOslabieniaOswietlenia = vec3(1,0,0);

float Oslabienie(float odleglosc)
{
    if(!OslabienieOswietlenia) return 1;
    else return 1.0/(WspolczynnikiOslabieniaOswietlenia[0]+
                     WspolczynnikiOslabieniaOswietlenia[1]*odleglosc+
                     WspolczynnikiOslabieniaOswietlenia[2]*odleglosc*odleglosc);
}

uniform bool Teksturowanie = true;
uniform sampler2D ProbnikTekstury;

vec4 ObliczKolorPhong(vec3 polozenie,vec3 normalna,vec4 kolor)
{
	vec3 R = polozenie;
	vec3 L = PolozenieZrodlaSwiatla-R;
	float odleglosc = length(L);
	float oslabienie = Oslabienie(odleglosc);
	L=normalize(L);
	vec3 N = normalize(normalna);
	float dotLN = dot(L,N);

	vec3 O = 2.0*dotLN*N-L;	//vec3 O = reflect(-L,N);
	vec3 V = normalize(PolozenieKamery-R);
	float dotOVn = pow(max(dot(O,V),0.0),WNs);

	dotLN = max(dotLN,0.0);

	vec4 teksel = vec4(1.0f, 1.0f, 1.0f, 1.0f);
	if(Teksturowanie) teksel = texture(ProbnikTekstury, wspTekstur);

	vec4 _kolor = Wa*Ca*kolor*teksel;
	_kolor+= oslabienie*Wd*Cd*kolor*teksel*dotLN;
	_kolor+= oslabienie*Ws*Cs*dotOVn;
	//_kolor = teksel; //Test teksturowania bez o�wietlenia
	return _kolor;
}

uniform bool CelShading = false;

float DyskretyzujWartosc(float wartosc)
{
	if(wartosc>=0 && wartosc <=0.25) return 0.1;
	if(wartosc>0.25 && wartosc <=0.5) return 0.4;
	if(wartosc>0.5 && wartosc <=0.75) return 0.7;
	return 1;
}

vec4 DyskretyzujKolor(vec4 kolor) //cel-shading
{
	kolor.r = DyskretyzujWartosc(kolor.r);
	kolor.g = DyskretyzujWartosc(kolor.g);
	kolor.b = DyskretyzujWartosc(kolor.b);
	return kolor;
}

vec4 Negatyw(vec4 kolor)
{
	kolor.rgb = 1 - kolor.rgb;
	return kolor;
}

vec4 ZmianaJasnosci(vec4 kolor, float wspolczynnik)
{
	kolor.rgb *= wspolczynnik;
	return kolor;
}

float Jasnosc(vec4 kolor)
{
	return (kolor.r + kolor.g + kolor.b)/3.0;
}

vec4 SkalaSzarosci(vec4 kolor)
{
	float jasnosc = Jasnosc(kolor);
	return vec4(jasnosc, jasnosc, jasnosc, kolor.a);
}

vec4 GammaCorrection(vec4 kolor, float gamma)
{	
	if(gl_FragCoord.x > 400) //demo
		kolor.rgb = pow(kolor.rgb, vec3(1.0/gamma));
	return kolor;
}

vec4 GoochJasnosc(vec4 kolor)
{
	float jasnosc = Jasnosc(kolor);
	kolor.r = jasnosc;
	kolor.g = 0;
	kolor.b = 1 - jasnosc;
	return kolor;
}

vec4 GoochDiffuse(vec3 polozenie,vec3 normalna)
{
	vec3 R = polozenie;
	vec3 L = PolozenieZrodlaSwiatla-R;
	L=normalize(L);
	vec3 N = normalize(normalna);
	float dotLN = dot(L,N);

	float wsp = 0.5 * (1 + dotLN); //[-1,1] -> [0,1]
	vec3 kolorZimny = vec3(255.0/255, 75.0/255, 75.0/255); 	
	vec3 kolorCieply = vec3(159.0/255, 148.0/255, 255.0/255); 	

	//pozniej dodane
	vec3 kolorBazowy = vec3(0.5, 0.5, 0.0); 
	kolorZimny = kolorZimny + kolorBazowy * 0.25;
	kolorCieply = kolorCieply + kolorBazowy * 0.25;
	
	vec3 kolor = mix(kolorZimny, kolorCieply, wsp);
	return vec4(kolor, 1);
}

vec4 FiltrZielony(vec4 kolor)
{
	kolor.r *= 0.05;
	kolor.g *= 0.9;
	kolor.b *= 0.05;
	return kolor;
}

float rand(vec2 pozycja)
{
    return fract(sin(dot(pozycja.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec4 Szum(vec4 kolor,vec2 pozycja)
{
	kolor.r *= rand(pozycja);
	kolor.g *= rand(pozycja);
	kolor.b *= rand(pozycja);
	return kolor;
}

uniform float Czas = 0;

vec4 Zaklocenia(vec4 kolor, float czas) //czas w sekundach
{	
	//kolor.g *= 0.5*(1+sin(0.05*(gl_FragCoord.y + 0.1*gl_FragCoord.x)));
	//kolor.b = 0.5*(1+sin(Czas));
	kolor.g *= 0.5*(1+sin(0.05*(gl_FragCoord.y + 0.1*gl_FragCoord.x) + 10*sin(0.5*Czas)));
	return kolor;
}

vec4 Wizjer(vec4 kolor, vec2 rozmiar)
{
	float r1 = 0.7;
	float r2 = 1;
	rozmiar /= 2;
	float x = (gl_FragCoord.x - rozmiar.x)/ rozmiar.x;
	float y = (gl_FragCoord.y - rozmiar.y)/ rozmiar.y;
	float r = x*x+y*y;
	//if(r>r1) kolor.rgb *= 0.5;
	//kolor.rgb /= r;
	if(r>r1) kolor.rgb *= 1 - (r - r1) / (r2 - r1);
	//if(r>r1) kolor.rgb *= smoothstep(1, 0, (r - r1) / (r2 - r1));
	if(r>r2) kolor.rgb = vec3(0);	
	return kolor;
}

vec4 CrossHatching(float jasnosc)
{
	vec3 kolor = vec3(0.9); //bialy papier
	vec3 kolorKreski = vec3(0.1); //czarny olowek
	float gestoscKresek = 10; //co ile pikseli

	if (jasnosc < 0.8) 
	{
		//kreska z lewego gornego rogu do prawego dolnego
		if (mod(gl_FragCoord.x + gl_FragCoord.y, gestoscKresek) == 0.0) 
		{
			kolor = kolorKreski;
		}
	}

	if (jasnosc < 0.6) 
	{
		//kreska z prawego gornego rogu do lewego dolnego
		if (mod(gl_FragCoord.x - gl_FragCoord.y, gestoscKresek) == 0.0) 
		{
			kolor = kolorKreski;
		}
	}

	if (jasnosc < 0.4) 
	{
	    //dodatkowa kreska z lewego gornego rogu do prawego dolnego
	    if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, gestoscKresek) == 0.0) 
	    {
			kolor = kolorKreski;
		}
	}

	if (jasnosc < 0.2) 
	{
		//dodatkowa kreska z prawego gornego rogu do lewego dolnego
		if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, gestoscKresek) == 0.0) 
		{
			kolor = kolorKreski;
		}
	} 

	return vec4(kolor, 1);
}

out vec4 kolor_out;

void main(void)
{
	kolor_out = ObliczKolorPhong(polozenie_scena,normalna_scena,kolor);
	if(CelShading) kolor_out = DyskretyzujKolor(kolor_out);

	//kolor_out = vec4(polozenie_scena.x,polozenie_scena.y,polozenie_scena.z,1.0);
	//kolor_out = Negatyw(kolor_out); //zadanie: zrobi� negatyw tylko we wskazanym prostok�cie ekranu (xmin, xmax) - (ymin, ymax)
	//kolor_out = ZmianaJasnosci(kolor_out, 0.1);
	//kolor_out = SkalaSzarosci(kolor_out);
	//kolor_out = GammaCorrection(kolor_out, 0.5);
	//kolor_out = GammaCorrection(kolor_out, 2);
	//kolor_out = GoochJasnosc(kolor_out); //uruchamiane po Phong
	//kolor_out = GoochDiffuse(polozenie_scena,normalna_scena); //samodzielny, bez Phonga

	/*
	kolor_out = FiltrZielony(kolor_out); //zrobi� jako zadanie
	//kolor_out = Szum(kolor_out, gl_FragCoord.xy);
	kolor_out = Szum(kolor_out, polozenie_kamera); //wymaga przekazania polozenie_kamera z vertex shadera
	kolor_out = ZmianaJasnosci(kolor_out, 1.5);	
	kolor_out = Zaklocenia(kolor_out, Czas); //wymaga dodania parametru Czas (ustalane w OknoGL::RysujScene)
	vec2 rozmiarOkna = vec2(800, 600); //rozmiar okna nale�a�oby przekazywa� jako parametr
	kolor_out = Wizjer(kolor_out, rozmiarOkna);
	*/

	//float jasnosc = Jasnosc(kolor_out);
	//jasnosc *= 2.5;
	//kolor_out = CrossHatching(jasnosc);

	//Zadanie: do vertex shader wprowadzic zalezne od czasu trzesienie (zmiana wektora gl_Position)
}